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.