Monday, June 26, 2017

java - Simple way to serialize save game data whilst allowing for future features


Is there a simple way to 'serialize' the game data of my game, but protected it from being unloadable if I add new fields? I have all the data in a single class, GameData.java, and I want to avoid having to manually read/write each field from it. If I serialise it using standard java function, but add new fields to the class, it will render it unserializable.


I'd like to be able to save the class and the reload it from a file, and it use default values for any new fields that are missing from the save file. XML may be a solution, but is there an existing library to automate the process?


Thanks!



Answer




I use the libGdx Json functionality to save my game state to JSON;


public class GameInstance
{
//Some fields, constructors, utilities

public void saveState(GameState state)
{
String save = json.prettyPrint(state);

//Save to the file using FileHandle

}

public void loadState(FileHandle file)
{
String stateText = file.toString();
json.setIgnoreUnknownFields(true);
state = json.fromJson(stateText);
}
}


In my GameState I store the version of my app;


public class GameState
{
//some fields
public final String versionID = "0.1.1";

//game access functions
}

Before I access the modified field, I check to see if the versionID is correct and will allow me to read it. This allows me to write simple fallback mechanics that help provide as much of the new functionality as possible.




I keep a field-changes.txt file that I use to log changes that I make in my fields for each class. I almost never remove a field entirely for compatability reasons. When I do I try to add functions that can work out a suitable replacement value.


Now, without libGdx you can just use the Jackson JSON API(link to tutorial on how to use Jackson). The details can be found in this Stack Overflow question. In short, there is apparently an annotation that you can use that has this purpose in mind specifically.


The accepted answer says you should do this;


import org.codehaus.jackson.annotate.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Foo
{
//...

}

Also check out the next best answer. Either way, the idea is still the same; to store the version of your GameState in each saved state and refactor the code to use the old data in alternative ways that makes the newest functionality possible.


Note: I only use libGdx and its Json library. Alternatively, if you wanted to use its Json library you could go and get the Json sourcecode. You would also need to copy the libGdx-specific collections and primitive collections to your project and fix the setup. You would have to do some minor editing to make it work.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...