Building a robust save system in LITIENGINE involves serializing transient game data (player health, coordinates, inventory, and environment flags) into a persistent format (such as JSON or binary files) and restoring that state into an active Environment.
packagecom.example.game.save;importjava.io.Serializable;importjava.util.ArrayList;importjava.util.List;publicclassSaveDataimplementsSerializable{privatestaticfinallongserialVersionUID=1L;// MetadatapublicStringsaveSlotName="Slot 1";publiclongtimestamp=System.currentTimeMillis();publicStringcurrentMapName="level1";// Player StatepublicdoubleplayerX=100.0;publicdoubleplayerY=150.0;publicintplayerHealth=100;publicintplayerMaxHealth=100;publicintgold=0;publicList<String>inventoryItems=newArrayList<>();// World Progress FlagspublicList<String>defeatedBosses=newArrayList<>();publicList<String>openedChests=newArrayList<>();}
packagecom.example.game.save;importde.gurkenlabs.litiengine.Game;importde.gurkenlabs.litiengine.entities.Creature;importde.gurkenlabs.litiengine.entities.Prop;importjava.io.*;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.Paths;publicclassSaveManager{privatestaticfinalStringSAVE_FOLDER="saves/";publicstaticvoidsaveGame(StringfileName,Creatureplayer){try{Pathfolder=Paths.get(SAVE_FOLDER);if(!Files.exists(folder)){Files.createDirectories(folder);}SaveDatadata=newSaveData();data.currentMapName=Game.world().environment().getMap().getName();data.playerX=player.getX();data.playerY=player.getY();data.playerHealth=player.getHitPoints();// Write binary serialized file (or JSON via Jackson/Gson)try(ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream(SAVE_FOLDER+fileName))){oos.writeObject(data);}System.out.println("Game saved successfully to "+fileName);}catch(IOExceptione){e.printStackTrace();}}publicstaticvoidloadGame(StringfileName,Creatureplayer){FilesaveFile=newFile(SAVE_FOLDER+fileName);if(!saveFile.exists()){System.err.println("Save file does not exist: "+fileName);return;}try(ObjectInputStreamois=newObjectInputStream(newFileInputStream(saveFile))){SaveDatadata=(SaveData)ois.readObject();// 1. Load the recorded map environmentGame.world().loadEnvironment(data.currentMapName);// 2. Restore player coordinates & statsplayer.setLocation(data.playerX,data.playerY);player.setHitPoints(data.playerHealth);// 3. Add player to the newly loaded environmentGame.world().environment().add(player);Game.world().camera().setFocus(player);System.out.println("Game state loaded from "+fileName);}catch(Exceptione){e.printStackTrace();}}}
To prevent chests from closing or dead bosses from respawning when reloading an environment:
// On environment loaded callback:Game.world().onLoaded(env->{for(StringchestId:currentSaveData.openedChests){Propchest=env.getProp(chestId);if(chest!=null){chest.setHitPoints(0);// Mark chest as opened/looted}}});
Write save data to a temporary file (save1.tmp) before renaming it to save1.dat. This ensures that if the game crashes or is closed mid-save, the player's existing save file is never corrupted.