From b113394e082edd52a3473316ecc1b6f35bbcf8be Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:59:53 +0800 Subject: [PATCH 1/5] Add number getters for Version --- src/client/java/minicraft/saveload/Version.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/client/java/minicraft/saveload/Version.java b/src/client/java/minicraft/saveload/Version.java index b388134be..057ffd51b 100644 --- a/src/client/java/minicraft/saveload/Version.java +++ b/src/client/java/minicraft/saveload/Version.java @@ -82,6 +82,11 @@ public int compareTo(@NotNull Version ov, boolean ignoreDev) { return 0; // The versions are equal. } + public int getMake() { return make; } + public int getMajor() { return major; } + public int getMinor() { return minor; } + public int getDev() { return dev; } + @Override public String toString() { return make + "." + major + "." + minor + (dev == 0 ? "" : "-dev" + dev); From b3841647b240c4f51a8afd9406bf88e8ca8329cc Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Tue, 9 Jan 2024 23:00:15 +0800 Subject: [PATCH 2/5] Add world and preferences backups --- src/client/java/minicraft/saveload/Load.java | 88 +++++++++++++++++++ src/client/java/minicraft/saveload/Save.java | 31 +++++++ .../resources/assets/localization/en-us.json | 2 + 3 files changed, 121 insertions(+) diff --git a/src/client/java/minicraft/saveload/Load.java b/src/client/java/minicraft/saveload/Load.java index efc17809a..c0f24ce99 100644 --- a/src/client/java/minicraft/saveload/Load.java +++ b/src/client/java/minicraft/saveload/Load.java @@ -3,6 +3,7 @@ import minicraft.core.Game; import minicraft.core.Updater; import minicraft.core.World; +import minicraft.core.io.FileHandler; import minicraft.core.io.Localization; import minicraft.core.io.Settings; import minicraft.entity.Arrow; @@ -59,6 +60,7 @@ import minicraft.screen.ResourcePackDisplay; import minicraft.screen.SkinDisplay; import minicraft.screen.TutorialDisplayHandler; +import minicraft.screen.WorldSelectDisplay; import minicraft.screen.entry.ListEntry; import minicraft.screen.entry.StringEntry; import minicraft.util.AdvancementElement; @@ -119,6 +121,87 @@ public Load(String worldname, boolean loadGame) { if (!loadGame) return; + // Is dev build + if (Game.VERSION.getDev() != 0 && worldVer.compareTo(Game.VERSION) < 0) { + Logging.SAVELOAD.info("Old world detected, backup prompting..."); + ArrayList entries = new ArrayList<>(); + entries.addAll(Arrays.asList(StringEntry.useLines(Color.WHITE, false, + Localization.getLocalized("minicraft.displays.save.popup_display.world_backup_prompt.msg", + worldVer, Game.VERSION)))); + entries.addAll(Arrays.asList(StringEntry.useLines("minicraft.display.popup.escape_cancel"))); + + AtomicBoolean acted = new AtomicBoolean(false); + AtomicBoolean continues = new AtomicBoolean(false); + AtomicBoolean doBackup = new AtomicBoolean(false); + + ArrayList callbacks = new ArrayList<>(); + callbacks.add(new PopupDisplay.PopupActionCallback("EXIT", m -> { + Game.exitDisplay(); + acted.set(true); + return true; + })); + + callbacks.add(new PopupDisplay.PopupActionCallback("ENTER|Y", m -> { + Game.exitDisplay(); + continues.set(true); + doBackup.set(true); + acted.set(true); + return true; + })); + + callbacks.add(new PopupDisplay.PopupActionCallback("N", m -> { + Game.exitDisplay(); + continues.set(true); + acted.set(true); + return true; + })); + + Game.setDisplay(new PopupDisplay(new PopupDisplay.PopupConfig( + "minicraft.displays.save.popup_display.world_backup_prompt", callbacks, 2), + entries.toArray(new ListEntry[0]))); + + while (true) { + if (acted.get()) { + if (continues.get()) { + if (doBackup.get()) { + Logging.SAVELOAD.info("Performing world backup..."); + int i = 0; + String filename = worldname; + File f = new File(location + "/saves/", filename); + while (f.exists()) { // Increments world name if world exists + i++; + filename = worldname + " (" + i + ")"; + f = new File(location + "/saves/", filename); + } + f.mkdirs(); + try { + FileHandler.copyFolderContents(Paths.get(location, "saves", worldname), + f.toPath(), FileHandler.SKIP, false); + } catch (IOException e) { + Logging.SAVELOAD.error(e, "Error occurs while performing world backup, loading aborted"); + throw new RuntimeException(new InterruptedException("World loading interrupted.")); + } + + Logging.SAVELOAD.info("World backup \"{}\" is created.", filename); + WorldSelectDisplay.updateWorlds(); + } else + Logging.SAVELOAD.warn("World backup is skipped."); + Logging.SAVELOAD.debug("World loading continues..."); + } else { + Logging.SAVELOAD.info("User cancelled world loading, loading aborted."); + throw new RuntimeException(new InterruptedException("World loading interrupted.")); + } + + break; + } + + try { + //noinspection BusyWait + Thread.sleep(10); + } catch (InterruptedException ignored) {} + } + } + if (worldVer.compareTo(new Version("1.9.2")) < 0) new LegacyLoad(worldname); else { @@ -189,6 +272,11 @@ public Load(String worldname, boolean loadGame) { break; } + + try { + //noinspection BusyWait + Thread.sleep(10); + } catch (InterruptedException ignored) {} } } } diff --git a/src/client/java/minicraft/saveload/Save.java b/src/client/java/minicraft/saveload/Save.java index b9a08424e..a96d70b55 100644 --- a/src/client/java/minicraft/saveload/Save.java +++ b/src/client/java/minicraft/saveload/Save.java @@ -46,6 +46,7 @@ import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; @@ -118,6 +119,36 @@ public Save(String worldname) { */ public Save() { this(new File(Game.gameDir + "/")); + + if (Game.VERSION.getDev() != 0) { // Is dev build + Logging.SAVELOAD.debug("In dev build: Searching for old preferences..."); + Version prefVer; + File prefFile = new File(location, "Preferences.json"); // Only this is checked when checking existence. + File unlocFile = new File(location, "Unlocks.json"); + try { + JSONObject json = new JSONObject(Load.loadFromFile(location + "Preferences.json", false)); + prefVer = new Version(json.getString("version")); + } catch (FileNotFoundException e) { + Logging.SAVELOAD.debug("Preferences.json is not found, ignoring..."); + prefVer = null; + } catch (IOException e) { + Logging.SAVELOAD.error(e, "Unable to load Preferences.json, saving aborted"); + return; + } + + if (prefVer != null && prefVer.compareTo(Game.VERSION) < 0) { + Logging.SAVELOAD.info("Old preferences detected, backup performing..."); + File prefBackupFile = new File(location + "Preferences.json.bak"); + if (prefBackupFile.exists()) Logging.SAVELOAD.info("Overwriting old Preferences.json backup..."); + if (prefBackupFile.delete()) Logging.SAVELOAD.trace("Preferences.json.bak is deleted."); + if (prefFile.renameTo(prefBackupFile)) Logging.SAVELOAD.trace("Preferences.json is renamed to Preferences.json.bak"); + File unlocBackupFile = new File(location + "Unlocks.json.bak"); + if (unlocBackupFile.exists()) Logging.SAVELOAD.info("Overwriting old Unlocks.json backup..."); + if (unlocBackupFile.delete()) Logging.SAVELOAD.trace("Unlocks.json.bak is deleted."); + if (unlocFile.renameTo(unlocBackupFile)) Logging.SAVELOAD.trace("Unlocks.json is renamed to Unlocks.json.bak"); + } + } + Logging.SAVELOAD.debug("Writing preferences and unlocks..."); writePrefs(); writeUnlocks(); diff --git a/src/client/resources/assets/localization/en-us.json b/src/client/resources/assets/localization/en-us.json index e10178853..15e918460 100644 --- a/src/client/resources/assets/localization/en-us.json +++ b/src/client/resources/assets/localization/en-us.json @@ -175,6 +175,8 @@ "minicraft.displays.resource_packs.display.help.position": "SHIFT-[LEFT|RIGHT|UP|DOWN] to move packs. ", "minicraft.displays.resource_packs.display.help.select": "%s to examine.", "minicraft.displays.resource_packs.display.title": "Resource Packs", + "minicraft.displays.save.popup_display.world_backup_prompt": "World Backup Prompt", + "minicraft.displays.save.popup_display.world_backup_prompt.msg": "The world is on version %s while you are on version %s. You are advised to perform a backup in case of irreversible world corruption. Should you like to perform a backup before continuing? (Y|N)", "minicraft.displays.skin": "Skins", "minicraft.displays.skin.display.help.move": "Use %s and %s to move.", "minicraft.displays.skin.display.help.select": "%s to select, and %s to cancel.", From a0a84bdf02fa5594c7e95cbed8124208decbea69 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:57:22 +0800 Subject: [PATCH 3/5] Remove Version#get...() --- src/client/java/minicraft/saveload/Load.java | 2 +- src/client/java/minicraft/saveload/Version.java | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/client/java/minicraft/saveload/Load.java b/src/client/java/minicraft/saveload/Load.java index c0f24ce99..5e0100013 100644 --- a/src/client/java/minicraft/saveload/Load.java +++ b/src/client/java/minicraft/saveload/Load.java @@ -122,7 +122,7 @@ public Load(String worldname, boolean loadGame) { if (!loadGame) return; // Is dev build - if (Game.VERSION.getDev() != 0 && worldVer.compareTo(Game.VERSION) < 0) { + if (Game.VERSION.isDev() && worldVer.compareTo(Game.VERSION) < 0) { Logging.SAVELOAD.info("Old world detected, backup prompting..."); ArrayList entries = new ArrayList<>(); entries.addAll(Arrays.asList(StringEntry.useLines(Color.WHITE, false, diff --git a/src/client/java/minicraft/saveload/Version.java b/src/client/java/minicraft/saveload/Version.java index 057ffd51b..615d3d568 100644 --- a/src/client/java/minicraft/saveload/Version.java +++ b/src/client/java/minicraft/saveload/Version.java @@ -82,10 +82,9 @@ public int compareTo(@NotNull Version ov, boolean ignoreDev) { return 0; // The versions are equal. } - public int getMake() { return make; } - public int getMajor() { return major; } - public int getMinor() { return minor; } - public int getDev() { return dev; } + public boolean isDev() { + return dev != 0; + } @Override public String toString() { From 399aa57bfb08b454b62a07559f85213f76f75972 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:59:35 +0800 Subject: [PATCH 4/5] Resolve removal error --- src/client/java/minicraft/saveload/Save.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/java/minicraft/saveload/Save.java b/src/client/java/minicraft/saveload/Save.java index a96d70b55..fb01cde17 100644 --- a/src/client/java/minicraft/saveload/Save.java +++ b/src/client/java/minicraft/saveload/Save.java @@ -120,7 +120,7 @@ public Save(String worldname) { public Save() { this(new File(Game.gameDir + "/")); - if (Game.VERSION.getDev() != 0) { // Is dev build + if (Game.VERSION.isDev()) { // Is dev build Logging.SAVELOAD.debug("In dev build: Searching for old preferences..."); Version prefVer; File prefFile = new File(location, "Preferences.json"); // Only this is checked when checking existence. From b8e221177db4918b142062605c257e22f9d97956 Mon Sep 17 00:00:00 2001 From: Litorom Date: Thu, 29 Aug 2024 14:22:43 -0400 Subject: [PATCH 5/5] Increment Version --- build.gradle | 2 +- src/client/java/minicraft/core/Game.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 01be4c064..e3918b62a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { allprojects { apply plugin: "java" - version = "2.2.1-dev1" + version = "2.2.1-dev2" sourceCompatibility = 8 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' diff --git a/src/client/java/minicraft/core/Game.java b/src/client/java/minicraft/core/Game.java index f2a97ab69..0be9e3420 100644 --- a/src/client/java/minicraft/core/Game.java +++ b/src/client/java/minicraft/core/Game.java @@ -25,7 +25,7 @@ protected Game() { public static final String NAME = "Minicraft Plus"; // This is the name on the application window. - public static final Version VERSION = new Version("2.2.1-dev1"); + public static final Version VERSION = new Version("2.2.1-dev2"); public static InputHandler input; // Input used in Game, Player, and just about all the *Menu classes. public static Player player;