Repository: movingblocks/destinationsol
Issue: Game Crashes When Resuming Previous Game After Upgrade from v1.4

### What you were trying to do
Resume the previous game after upgrading from version 1.4.1 (the current Steam version) to version 2.0.0.

### What actually happened
The game crashed after choosing "continue"

### How to reproduce
The hull values have changed in prevShip.ini between v1.4.1 and v2.0.0. Upgrading from v1.4.1 to v2.0.0 is the proper way to reproduce this issue, however the following steps allow you to reproduce this issue

Step 1 - In the prevShip.ini file, change the value of hull to imperialSmall instead of core:imperialSmall
Step 2 - Run the game and choose Play Game and then Continue.

### Log details and game version

```
java.lang.RuntimeException: Invalid resource name (missing namespace?) `imperialSmall`
	at org.destinationsol.assets.Assets.parsePath(Assets.java:69)
	at org.destinationsol.assets.Assets.getJson(Assets.java:156)
	at org.destinationsol.assets.json.Validator.getValidatedJSON(Validator.java:34)
	at org.destinationsol.files.HullConfigManager.read(HullConfigManager.java:115)
	at org.destinationsol.files.HullConfigManager.getConfig(HullConfigManager.java:96)
	at org.destinationsol.game.SaveManager.readShip(SaveManager.java:209)
	at org.destinationsol.game.SolGame.readShipFromConfigOrLoadFromSaveIfNull(SolGame.java:238)
	at org.destinationsol.game.SolGame.createGame(SolGame.java:221)
	at org.destinationsol.game.SolGame.<init>(SolGame.java:198)
	at org.destinationsol.SolApplication.play(SolApplication.java:255)
	at org.destinationsol.menu.LoadingScreen.updateCustom(LoadingScreen.java:47)
	at org.destinationsol.ui.SolInputManager.update(SolInputManager.java:238)
	at org.destinationsol.SolApplication.update(SolApplication.java:204)
	at org.destinationsol.SolApplication.safeUpdate(SolApplication.java:182)
	at org.destinationsol.SolApplication.render(SolApplication.java:146)
	at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Window.update(Lwjgl3Window.java:392)
	at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.loop(Lwjgl3Application.java:137)
	at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:111)
	at org.destinationsol.desktop.SolDesktop.main(SolDesktop.java:149)
```

### Computer details
N/A

Changed files:
engine/src/main/java/org/destinationsol/menu/NewGameScreen.java, engine/src/main/java/org/destinationsol/game/SaveManager.java, engine/src/main/java/org/destinationsol/Const.java

diff --git a/engine/src/main/java/org/destinationsol/Const.java b/engine/src/main/java/org/destinationsol/Const.java
index 0585d918..d8c8b166 100644
--- a/engine/src/main/java/org/destinationsol/Const.java
+++ b/engine/src/main/java/org/destinationsol/Const.java
@@ -37,4 +37,8 @@ public class Const {
     public static final float CAM_VIEW_DIST_JOURNEY = 8.6f;
     public static final float DEFAULT_AI_SPD = 4f;
     public static final float BIG_AI_SPD = 2f;
+
+    public static final String SAVE_FILE_NAME = "prevShip.ini";
+    public static final String MERC_SAVE_FILE = "mercenaries.json";
+    public static final String WORLD_SAVE_FILE_NAME = "world.json";
 }
diff --git a/engine/src/main/java/org/destinationsol/game/SaveManager.java b/engine/src/main/java/org/destinationsol/game/SaveManager.java
index 201c9ed2..833e8b92 100644
--- a/engine/src/main/java/org/destinationsol/game/SaveManager.java
+++ b/engine/src/main/java/org/destinationsol/game/SaveManager.java
@@ -23,6 +23,7 @@
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.stream.JsonReader;
+import org.destinationsol.Const;
 import org.destinationsol.IniReader;
 import org.destinationsol.common.SolRandom;
 import org.destinationsol.files.HullConfigManager;
@@ -47,9 +48,6 @@
 import java.util.List;
 
 public class SaveManager {
-    protected static final String SAVE_FILE_NAME = "prevShip.ini";
-    protected static final String MERC_SAVE_FILE = "mercenaries.json";
-    protected static final String WORLD_SAVE_FILE_NAME = "world.json";
 
     private static Logger logger = LoggerFactory.getLogger(SaveManager.class);
 
@@ -66,7 +64,8 @@ public static void writeShips(HullConfig hull, float money, List<SolItem> itemsL
 
         String waypoints = waypointsToString(hero.getWaypoints());
 
-        IniReader.write(SAVE_FILE_NAME, "hull", hullName, "money", (int) money, "items", items, "x", pos.x, "y", pos.y, "waypoints", waypoints);
+        IniReader.write(Const.SAVE_FILE_NAME, "hull", hullName, "money", (int) money, "items", items,
+                "x", pos.x, "y", pos.y, "waypoints", waypoints, "version", Const.VERSION);
     }
 
     private static String waypointsToString(ArrayList<Waypoint> waypoints) {
@@ -156,7 +155,7 @@ private static void writeMercs(Hero hero, HullConfigManager hullConfigManager) {
         // Using PrintWriter because it truncates the file if it exists or creates a new one if it doesn't
         // And truncation is good because we don't want dead mercs respawning
         try {
-            writer = new PrintWriter(getResourcePath(MERC_SAVE_FILE), "UTF-8");
+            writer = new PrintWriter(getResourcePath(Const.MERC_SAVE_FILE), "UTF-8");
             writer.write(stringToWrite);
             writer.close();
         } catch (FileNotFoundException | UnsupportedEncodingException e) {
@@ -189,17 +188,23 @@ public static boolean resourceExists(String fileName) {
     }
 
     /**
-     * Tests is the game has a previous ship (a game to continue)
+     * Tests if the game has a compatible previous ship (a game to continue)
      */
-    public static boolean hasPrevShip(String fileName) {
-        return resourceExists(fileName);
+    public static boolean hasPreviousCompatibleShip() {
+        if (!resourceExists(Const.SAVE_FILE_NAME)) {
+            return false;
+        }
+        IniReader reader = new IniReader(Const.SAVE_FILE_NAME, null);
+        String saveMajorVersion = reader.getString("version", "").split("\\\\.")[0];
+        String gameMajorVersion = Const.VERSION.split("\\\\.")[0];
+        return saveMajorVersion.equals(gameMajorVersion);
     }
 
     /**
      * Load last saved ship from file
      */
     public static ShipConfig readShip(HullConfigManager hullConfigs, ItemManager itemManager) {
-        IniReader ir = new IniReader(SAVE_FILE_NAME, null);
+        IniReader ir = new IniReader(Const.SAVE_FILE_NAME, null);
 
         String hullName = ir.getString("hull", null);
         if (hullName == null) {
@@ -229,7 +234,7 @@ public static ShipConfig readShip(HullConfigManager hullConfigs, ItemManager ite
      */
     public static void saveWorld(int numberOfSystems) {
         Long seed = SolRandom.getSeed();
-        String fileName = SaveManager.getResourcePath(WORLD_SAVE_FILE_NAME);
+        String fileName = SaveManager.getResourcePath(Const.WORLD_SAVE_FILE_NAME);
 
         JsonObject world = new JsonObject();
         world.addProperty("seed", seed);
@@ -257,11 +262,11 @@ public static void saveWorld(int numberOfSystems) {
      * Load the last saved world from file, or returns null if there is no file
      */
     public static WorldConfig loadWorld() {
-        if (SaveManager.resourceExists(WORLD_SAVE_FILE_NAME)) {
+        if (SaveManager.resourceExists(Const.WORLD_SAVE_FILE_NAME)) {
             WorldConfig config = new WorldConfig();
             JsonReader reader = null;
             try {
-                reader = new com.google.gson.stream.JsonReader(new FileReader(SaveManager.getResourcePath(WORLD_SAVE_FILE_NAME)));
+                reader = new com.google.gson.stream.JsonReader(new FileReader(SaveManager.getResourcePath(Const.WORLD_SAVE_FILE_NAME)));
                 reader.setLenient(true); // without this it will fail with strange errors
                 JsonObject world = new JsonParser().parse(reader).getAsJsonObject();
 
diff --git a/engine/src/main/java/org/destinationsol/menu/NewGameScreen.java b/engine/src/main/java/org/destinationsol/menu/NewGameScreen.java
index 86494669..9ef2f156 100644
--- a/engine/src/main/java/org/destinationsol/menu/NewGameScreen.java
+++ b/engine/src/main/java/org/destinationsol/menu/NewGameScreen.java
@@ -58,7 +58,7 @@ public class NewGameScreen extends SolUiBaseScreen {
 
     @Override
     public void onAdd(SolApplication solApplication) {
-        continueControl.setEnabled(SaveManager.hasPrevShip("prevShip.ini"));
+        continueControl.setEnabled(SaveManager.hasPreviousCompatibleShip());
     }
 
     @Override