diff --git a/gradle.properties b/gradle.properties index 0d507c2..42b36aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,6 +5,6 @@ loader_version=0.14.24 mod_id=quickbackupmulti mod_name=QuickBackupMulti -mod_version=1.0.2 +mod_version=1.0.1 maven_group=dev.skydynamic archives_base_name=QuickBackupMulti \ No newline at end of file diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/QuickBackupMulti.java b/src/main/java/dev/skydynamic/quickbackupmulti/QuickBackupMulti.java index f8f69ac..a161be0 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/QuickBackupMulti.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/QuickBackupMulti.java @@ -1,9 +1,11 @@ package dev.skydynamic.quickbackupmulti; +import dev.skydynamic.quickbackupmulti.i18n.Translate; import dev.skydynamic.quickbackupmulti.utils.config.Config; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.ModContainer; //#if MC>=11900 import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; //#else @@ -19,18 +21,29 @@ import static dev.skydynamic.quickbackupmulti.command.QuickBackupMultiCommand.RegisterCommand; public final class QuickBackupMulti implements ModInitializer { + public static final String MODID = "quickbackupmulti"; + public static final Logger LOGGER = LoggerFactory.getLogger("QuickBackupMulti"); EnvType env = FabricLoader.getInstance().getEnvironmentType(); @Override public void onInitialize() { + ModContainer qbm = FabricLoader.getInstance().getModContainer(MODID) + .orElseThrow(() -> new IllegalStateException("Couldn't find the mod container for QuickBackupMulti")); + + Config.INSTANCE.load(); + Translate.handleResourceReload(Config.INSTANCE.getLang()); + //#if MC>=11900 CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> RegisterCommand(dispatcher)); //#else //$$ CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> RegisterCommand(dispatcher)); //#endif - ServerLifecycleEvents.SERVER_STARTED.register(server -> Config.TEMP_CONFIG.setServerValue(server)); + ServerLifecycleEvents.SERVER_STARTED.register(server -> { + Config.TEMP_CONFIG.setServerValue(server); + Config.TEMP_CONFIG.setEnv(env); + }); ServerLifecycleEvents.SERVER_STOPPED.register(server -> { if (Config.TEMP_CONFIG.isBackup) { if (env == EnvType.SERVER) { diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/command/QuickBackupMultiCommand.java b/src/main/java/dev/skydynamic/quickbackupmulti/command/QuickBackupMultiCommand.java index fcac5ab..be8261c 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/command/QuickBackupMultiCommand.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/command/QuickBackupMultiCommand.java @@ -1,7 +1,6 @@ package dev.skydynamic.quickbackupmulti.command; import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; @@ -109,7 +108,7 @@ private static int deleteSaveBackup(ServerCommandSource commandSource, int slot) } private static int restoreSaveBackup(ServerCommandSource commandSource, int slot) { - if (!backupDir.resolve("Slot" + slot + "_info.json").toFile().exists()) { + if (!getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists()) { Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.restore.fail"))); return 0; } @@ -131,7 +130,7 @@ private static void executeRestore(ServerCommandSource commandSource) { //#endif synchronized (QbDataHashMap) { if (QbDataHashMap.containsKey("QBM")) { - if (!backupDir.resolve("Slot" + QbDataHashMap.get("QBM").get("Slot") + "_info.json").toFile().exists()) { + if (!getBackupDir().resolve("Slot" + QbDataHashMap.get("QBM").get("Slot") + "_info.json").toFile().exists()) { Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.restore.fail"))); QbDataHashMap.clear(); return; diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServerMixin.java b/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServerMixin.java deleted file mode 100644 index ddff9e4..0000000 --- a/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServerMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -package dev.skydynamic.quickbackupmulti.mixin; - -import dev.skydynamic.quickbackupmulti.utils.config.Config; - -import dev.skydynamic.quickbackupmulti.i18n.Translate; -import net.minecraft.server.MinecraftServer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.nio.file.Path; - -import static dev.skydynamic.quickbackupmulti.QuickBackupMulti.LOGGER; -import static dev.skydynamic.quickbackupmulti.i18n.Translate.tr; - -@Mixin(MinecraftServer.class) -public abstract class MinecraftServerMixin { - - @Inject(method = "", at = @At("RETURN")) - private void onServerInit(CallbackInfo ci) { - Config.INSTANCE.load(); - Translate.handleResourceReload(Config.INSTANCE.getLang()); - } - - @Inject(method = "loadWorld", at = @At("RETURN")) - private void initQuickBackupMulti(CallbackInfo ci) { - Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/"); - if (!backupDir.toFile().exists()) { - LOGGER.info(tr("quickbackupmulti.init.start")); - backupDir.toFile().mkdir(); - LOGGER.info(tr("quickbackupmulti.init.finish")); - } - for(int j=1; j<=Config.INSTANCE.getNumOfSlot(); j++) { - if (!backupDir.resolve("Slot" + j).toFile().exists()) backupDir.resolve("Slot" + j).toFile().mkdir(); - } - } - -} diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ClientMixin.java b/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ClientMixin.java new file mode 100644 index 0000000..f37f085 --- /dev/null +++ b/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ClientMixin.java @@ -0,0 +1,29 @@ +package dev.skydynamic.quickbackupmulti.mixin; + +import dev.skydynamic.quickbackupmulti.utils.config.Config; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.nio.file.Path; + +import static dev.skydynamic.quickbackupmulti.utils.QbmManager.createBackupDir; + +@Environment(EnvType.CLIENT) +@Mixin(MinecraftServer.class) +public abstract class MinecraftServer_ClientMixin { + + @Inject(method = "loadWorld", at = @At("RETURN")) + private void initQuickBackupMultiClient(CallbackInfo ci) { + MinecraftServer server = (MinecraftServer) (Object) this; + Config.TEMP_CONFIG.setServerValue(server); + String worldName = server.getSaveProperties().getLevelName(); + Config.TEMP_CONFIG.setWorldName(worldName); + Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/").resolve(worldName); + createBackupDir(backupDir); + } +} diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ServerMixin.java b/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ServerMixin.java new file mode 100644 index 0000000..61fe2e3 --- /dev/null +++ b/src/main/java/dev/skydynamic/quickbackupmulti/mixin/MinecraftServer_ServerMixin.java @@ -0,0 +1,24 @@ +package dev.skydynamic.quickbackupmulti.mixin; + +import net.fabricmc.api.Environment; +import net.fabricmc.api.EnvType; +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.nio.file.Path; + +import static dev.skydynamic.quickbackupmulti.utils.QbmManager.createBackupDir; + +@Environment(EnvType.SERVER) +@Mixin(MinecraftServer.class) +public abstract class MinecraftServer_ServerMixin { + @Inject(method = "loadWorld", at = @At("RETURN")) + private void initQuickBackupMulti(CallbackInfo ci) { + Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/"); + createBackupDir(backupDir); + } + +} diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/utils/QbmManager.java b/src/main/java/dev/skydynamic/quickbackupmulti/utils/QbmManager.java index ad15f25..ef001f1 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/utils/QbmManager.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/utils/QbmManager.java @@ -5,6 +5,8 @@ import dev.skydynamic.quickbackupmulti.utils.config.Config; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.world.ServerWorld; @@ -26,16 +28,24 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import static dev.skydynamic.quickbackupmulti.QuickBackupMulti.LOGGER; import static dev.skydynamic.quickbackupmulti.i18n.Translate.tr; public class QbmManager { - public static Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/"); public static Path savePath = Config.TEMP_CONFIG.server.getSavePath(WorldSavePath.ROOT); public static IOFileFilter fileFilter = new NotFileFilter(new NameFileFilter(Config.INSTANCE.getIgnoredFiles())); static Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); + public static Path getBackupDir() { + if (Config.TEMP_CONFIG.env == EnvType.SERVER) { + return backupDir; + } else { + return backupDir.resolve(Config.TEMP_CONFIG.worldName); + } + } + private static class SlotInfoStorage { String desc; long timestamp; @@ -59,7 +69,7 @@ private static void writeBackupInfo(int slot, String desc) { ConcurrentHashMap data = new ConcurrentHashMap<>(); data.put("desc", desc); data.put("timestamp", System.currentTimeMillis()); - var writer = new FileWriter(backupDir.resolve("Slot" + slot + "_info.json").toFile()); + var writer = new FileWriter(getBackupDir().resolve("Slot" + slot + "_info.json").toFile()); gson.toJson(data, writer); writer.close(); } catch (Exception e) { @@ -73,11 +83,11 @@ private static long getDirSize(File dir) { } private static boolean checkSlotExist(int slot) { - return backupDir.resolve("Slot" + slot + "_info.json").toFile().exists(); + return getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists(); } public static void restoreClient(int slot) { - File targetBackupSlot = backupDir.resolve("Slot" + slot).toFile(); + File targetBackupSlot = getBackupDir().resolve("Slot" + slot).toFile(); try { savePath.resolve("level.dat").toFile().delete(); savePath.resolve("level.dat_old").toFile().delete(); @@ -103,7 +113,7 @@ public static void restoreClient(int slot) { } public static void restore(int slot) { - File targetBackupSlot = backupDir.resolve("Slot" + slot).toFile(); + File targetBackupSlot = getBackupDir().resolve("Slot" + slot).toFile(); try { // var it = Files.walk(savePath,5).sorted(Comparator.reverseOrder()).iterator(); // while (it.hasNext()){ @@ -145,9 +155,9 @@ public static int make(ServerCommandSource commandSource, int slot, String desc) if (serverWorld == null || serverWorld.savingDisabled) continue; serverWorld.savingDisabled = true; } - if (!backupDir.resolve("Slot" + slot).toFile().exists()) backupDir.resolve("Slot" + slot).toFile().mkdir(); - if (Objects.requireNonNull(backupDir.resolve("Slot" + slot).toFile().listFiles()).length > 0) FileUtils.deleteDirectory(backupDir.resolve("Slot" + slot).toFile()); - FileUtils.copyDirectory(savePath.toFile(), backupDir.resolve("Slot" + slot).toFile(), fileFilter); + if (!getBackupDir().resolve("Slot" + slot).toFile().exists()) getBackupDir().resolve("Slot" + slot).toFile().mkdir(); + if (Objects.requireNonNull(getBackupDir().resolve("Slot" + slot).toFile().listFiles()).length > 0) FileUtils.deleteDirectory(getBackupDir().resolve("Slot" + slot).toFile()); + FileUtils.copyDirectory(savePath.toFile(), getBackupDir().resolve("Slot" + slot).toFile(), fileFilter); long endTime = System.currentTimeMillis(); double intervalTime = (endTime - startTime) / 1000.0; Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.make.success", intervalTime))); @@ -169,7 +179,7 @@ public static MutableText list() { try { MutableText backText = Messenger.literal("§2[▷] "); MutableText deleteText = Messenger.literal("§c[×] "); - var reader = new FileReader(backupDir.resolve("Slot" + j + "_info.json").toFile()); + var reader = new FileReader(getBackupDir().resolve("Slot" + j + "_info.json").toFile()); var result = gson.fromJson(reader, SlotInfoStorage.class); reader.close(); int finalJ = j; @@ -179,7 +189,7 @@ public static MutableText list() { .styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of(tr("quickbackupmulti.list_backup.slot.delete", finalJ))))); String desc = result.desc; if (Objects.equals(result.desc, "")) desc = tr("quickbackupmulti.empty_comment"); - long backupSizeB = getDirSize(backupDir.resolve("Slot" + j).toFile()); + long backupSizeB = getDirSize(getBackupDir().resolve("Slot" + j).toFile()); totalBackupSizeB += backupSizeB; double backupSizeMB = (double) backupSizeB / FileUtils.ONE_MB; double backupSizeGB = (double) backupSizeB / FileUtils.ONE_GB; @@ -190,7 +200,7 @@ public static MutableText list() { .append("§a" + sizeString) .append(String.format(" §b%s§7: §r%s", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(result.timestamp), desc)); } catch (IOException e) { - resultText.append(Messenger.literal("\n"+ tr("quickbackupmulti.list_backup.slot.header", j) + " §2[▷] §c[×] §r") + tr("quickbackupmulti.empty_comment")); + resultText.append("\n"+ tr("quickbackupmulti.list_backup.slot.header", j) + " §2[▷] §c[×] §r" + tr("quickbackupmulti.empty_comment")); } } double totalBackupSizeMB = (double) totalBackupSizeB / FileUtils.ONE_MB; @@ -201,10 +211,10 @@ public static MutableText list() { } public static boolean delete(int slot) { - if (backupDir.resolve("Slot" + slot + "_info.json").toFile().exists() || backupDir.resolve("Slot" + slot).toFile().exists()) { + if (getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists() || getBackupDir().resolve("Slot" + slot).toFile().exists()) { try { - backupDir.resolve("Slot" + slot + "_info.json").toFile().delete(); - FileUtils.deleteDirectory(backupDir.resolve("Slot" + slot).toFile()); + getBackupDir().resolve("Slot" + slot + "_info.json").toFile().delete(); + FileUtils.deleteDirectory(getBackupDir().resolve("Slot" + slot).toFile()); return true; } catch (SecurityException | IOException e) { return false; @@ -212,4 +222,15 @@ public static boolean delete(int slot) { } else return false; } + public static void createBackupDir(Path path) { + if (!path.toFile().exists()) { + LOGGER.info(tr("quickbackupmulti.init.start")); + path.toFile().mkdirs(); + LOGGER.info(tr("quickbackupmulti.init.finish")); + } + for(int j = 1; j<= Config.INSTANCE.getNumOfSlot(); j++) { + if (!path.resolve("Slot" + j).toFile().exists()) path.resolve("Slot" + j).toFile().mkdir(); + } + } + } diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/ConfigStorage.java b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/ConfigStorage.java index 76caa3c..0133b9b 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/ConfigStorage.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/ConfigStorage.java @@ -4,15 +4,17 @@ public class ConfigStorage { @Ignore - public static final ConfigStorage DEFAULT = new ConfigStorage(5, new ArrayList<>(List.of("session.lock")), "zh_cn"); + public static final ConfigStorage DEFAULT = new ConfigStorage(5, new ArrayList<>(List.of("session.lock")), "zh_cn", true); int numOfSlots; ArrayList ignoredFiles; String lang; + boolean shouldCheckUpdate; - public ConfigStorage(int NumOfSlots, ArrayList IgnoredFiles, String lang) { + public ConfigStorage(int NumOfSlots, ArrayList IgnoredFiles, String lang, boolean shouldCheckUpdate) { this.numOfSlots = NumOfSlots; this.ignoredFiles = IgnoredFiles; this.lang = lang; + this.shouldCheckUpdate = shouldCheckUpdate; } public int getNumOfSlots() { @@ -27,8 +29,12 @@ public String getLang() { return this.lang; } + public boolean getShouldCheckUpdate() { + return this.shouldCheckUpdate; + } + @Override public int hashCode() { - return Objects.hash(getNumOfSlots(), getIgnoredFiles(), getLang()); + return Objects.hash(getNumOfSlots(), getIgnoredFiles(), getLang(), getShouldCheckUpdate()); } } diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QbmTempConfig.java b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QbmTempConfig.java index 12af7a4..db5e67f 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QbmTempConfig.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QbmTempConfig.java @@ -1,11 +1,14 @@ package dev.skydynamic.quickbackupmulti.utils.config; +import net.fabricmc.api.EnvType; import net.minecraft.server.MinecraftServer; public class QbmTempConfig { public Boolean isBackup = false; public MinecraftServer server; public int backupSlot; + public EnvType env; + public String worldName; public void setIsBackupValue(Boolean value) { this.isBackup = value; @@ -19,4 +22,12 @@ public void setBackupSlot(int slot) { this.backupSlot = slot; } + public void setEnv(EnvType env) { + this.env = env; + } + + public void setWorldName(String worldName) { + this.worldName = worldName; + } + } diff --git a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QuickBackupMultiConfig.java b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QuickBackupMultiConfig.java index 8bbf8ef..c66e9c6 100644 --- a/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QuickBackupMultiConfig.java +++ b/src/main/java/dev/skydynamic/quickbackupmulti/utils/config/QuickBackupMultiConfig.java @@ -96,6 +96,12 @@ public String getLang() { } } + public boolean getShouldCheckUpdate() { + synchronized (lock) { + return configStorage.shouldCheckUpdate; + } + } + public void setLang(String lang) { synchronized (lock) { configStorage.lang = lang; diff --git a/src/main/resources/quickbackupmulti.mixins.json b/src/main/resources/quickbackupmulti.mixins.json index 3798dbb..c1e96af 100644 --- a/src/main/resources/quickbackupmulti.mixins.json +++ b/src/main/resources/quickbackupmulti.mixins.json @@ -2,13 +2,15 @@ "required": true, "package": "dev.skydynamic.quickbackupmulti.mixin", "compatibilityLevel": "JAVA_17", - "mixins": [ - "MinecraftServerMixin" - ], + "mixins": [], "injectors": { "defaultRequire": 1 }, + "server": [ + "MinecraftServer_ServerMixin" + ], "client": [ - "MinecraftClientMixin" + "MinecraftClientMixin", + "MinecraftServer_ClientMixin" ] } \ No newline at end of file