Backwards-Forewords Compatible Save Game Data

I’ve got an idea on storing saved games that I think is generally useful and helpful, so I felt I should share it somewhere.

Several months ago I was wracking my brain, looking for a strategy for storing a potentially large set of data for a given 2D game world made up of blocks and a friend sparked a fascinating piece of inspiration for me. I was debating an XML format vs. some kind of custom-designed binary format and zip files came up in the discussion (he was just throwing out odd-ball ideas, trying to help me out).

That’s when the thought hit me full force: zip files are the perfect solution (and Java supports them out of the box, woo!), allowing both backwards and forwards compatibility in my game world format. My thinking (and what I’ve been working on) is that the zip archive holds each distinct type of data as a separate file in the archive. When you need a new type of data, just slap a new file into the archive under a new name. If an older version needs to load the file, it simply ignores data files it knows nothing about. When a newer version loads the file, it can supply reasonable defaults for the data it considers to be missing or otherwise extrapolate from existing data (what we’d have to do on old files opened in a new version, anyhow).

The beauty of this is that as your needs change and evolve over time, your method for storing new data does not interfere with or even change the way you store old data, unless you’re brave/foolish enough to re-arrange the archive’s structure later on. Another nice bonus is that you get compression for free, if you want it (one can always set the ZIPOutputStream to simply store files instead of compressing them). Even setting the compression level to it’s minimum setting gets you some rather good run-length encoding for only minimal processor usage.

As a more concrete example: the game engine I’m working on uses a number of run-time defined variables in game worlds that are specified mostly by XML files from game mods. Each block in the world gets it’s own little chunk of data for each variable. From one run to the next, as mods are added and removed from the game, some of these variables may no longer be required.

Since each variable is a primitive type (byte, short, int, long, float or double), all I have to do when storing or loading them is read/write a bunch of raw data to/from the stream, without dealing with all the data being mixed together. Each variable has it’s own file and an extension matching it’s primitive type, so anyone poking around in the files in the archive can be assured of the exact type of data based on it’s name alone, though discovering it’s exact purpose may require looking it up in the meta-data (see next paragraph).

For textual data, like Strings, I’m storing them in XML files. I’m also storing some minimal meta-data as XML, like the dimensions of the world and a listing of the block types by name, so the world can be reconstructed from the raw numbers from other files.

Now, one hiccup I can see is that sometimes you’re going to end up with data you don’t know how to parse, because it’s either no longer supported, or the mod that needs it was removed. I currently haven’t decided on how to handle that. It’s possible to preserve the old data and hold it in memory until the world is written to disk again, but this would not always be desired. I think discarding it is probably the way I’ll go. It can always be manually retrieved from an old copy and re-inserted just by manipulating the zip archive a bit.

Another hiccup I see is that once you decide where in the archive a file goes, you can’t ever move it without breaking compatibility with older versions. So, if you make an ugly choice on placement of a file, you’re stuck with it.

Anyway, that’s my idea. I hope others find in helpful.

Interesting. I posted a question so Gamedev on Stack Overflow asking about a problem that your solution seems to solve ( https://gamedev.stackexchange.com/questions/120064/simple-way-to-serialize-save-game-data-whilst-allowing-for-future-features ) and a solution on there was to store it as Json.

I’ve been poking around the internet trying to see if anyone has ever tried this before. I’ve seen no evidence of it, so I felt I should share.

This could easily be used with other archive formats and other programming languages, but this is an old forum I used to visit…so, seemed the logical first place.

It sounds good. I wasn’t criticising at all; your post just reminded me of something I’d briefly looked into before. :slight_smile: I think my low attention span meant that I’d got bored of my project I was working on at the time long before I implemented anything.

Zip files are just a box to store things in. Sure, it’s useful to have a standard box,
but over time the nature of what gets stored will change so much that having a
box won’t help much.

It takes careful planning to remain compatible, and sometimes it’s not possible.
The very first step is to embed a version descriptor in the saved format, so
future versions can have a chance to know what they’re dealing with.

My thoughts:

When finding a solution for versionising data, these are two different things:
The concept itself and the way to store data. Using text, binary, json or xml is not part of the design at first place.

One main part of a data version concept is about processing the data.

Your approach is actually not using zip files, but a file system (thats what you get with zip files). Nothing fundamentelly wrong with that of course.

Always favor simple solutions. Not clearly separating versioned data lets complexity explode.