Sep 29

Save games

Tag: Full Games,MMORPG Tycoontrevor @ 8:16 pm

One of the biggest nightmares for me in MMORPG Tycoon 1 and 1.1 was that of save game support.  In version 1, there was well over a megabyte of binary data that had to be saved and loaded successfully, to resume a game in progress.  In version 1.1, that size was growing drastically, as all sorts of new configurable settings and a new, much more complicated subscriber AI model were added.  But even worse than simply maintaining those save files, I needed to support loading in save games saved in earlier versions, and converting that data to a new format so that it could be used by the new game (as happened between versions 1.0.6 and 1.0.7, for example)

Those save files are going to be getting much, much larger again in version 2.0, and I imagine that the save file format will continue changing even after release, as I add further new features.  So I’m spending a little time investigating strategies which will hopefully ease the burden of managing those save files..  I was already using serialisation (which basically allows one to write a single piece of code which handles both saving and loading, instead of having to write two separate functions and manually keep the two in synch), but even that wasn’t helping enough.  Now I’m looking into moving to a property-based system, or possibly even to a full-blown reflection-type system, either of which would essentially be able to understand their own data well enough to write their own save/load routines automatically, at the expense of a slightly more complicated codebase, and perhaps some small amount of lost performance.

But I’m not sure.  I’m still thinking it over.  Designing and implementing something like a reflection system in C++ (which is not at all designed to support that type of language feature) can be rather brain-melting, I’m finding.  Especially since I’m so picky about what my code needs to look like.

6 Responses to “Save games”

  1. Awesome Dino says:

    Call upon the Programming God and tell him to do everything for you because you’re too awesome.

  2. Dan Haraj says:

    I hope you don’t try to implement reflection in C++. That way lies folly. If you need reflection, perhaps it’s time to migrate to a language like C#. It should still meet your other needs adequately, no?

  3. Marte says:

    Hi!
    I’m following your progress and your problem with save game is quite intersting.
    Implementing reflections in c++ can be really difficult, maybe you can try to find a sort fo XStream (made for java) in c++?
    But my comment is about how to mantain this kind of incremental and not-incremental informations.
    IMHO is a big problem, and for me a solution can be to save into an archive (zip or whatever you want) not ONE big file, but many files: one for configurations, one for player status, one for world status, one for statistics and so on..
    So changes can be managed more easly and, when you move into new version, identify with more detail what do you change or not.
    Now, i don’t know your system (i’m a Java programmer), but i think that using Singleton,Factory, Business Delegate patterns on loading/saving this kind of information can help you a lot to keep control on your save/load subsystem. In particular maybe using not binary file but text file in one format (xml,csv, etc..) can help you into debug phase.
    Image to move from 1.0 to 1.1: if some of your users have some problems with save file, you can say “please send me your save file”. If this file is human-readable, you can compare with many programs with your “skeleton” or “example save file” and find problem not on skeleton but into values.

    What do you think?

  4. trevor says:

    @Dan: C# doesn’t have good cross-platform support, currently. The Mono project does exist, but it’s not supported well enough for me to feel comfortable using it for anything non-Windows, yet.

    In the end, I’ve chosen to set up a system whereby I can declare the particular member variables that I’m interested in saving/loading, and subsequently have those bits of data managed automatically by the save/load code. This is integrated nicely with an object factory, to make the load doubly-painless. It also easily allows for these variables to be changed, moved, added, removed, or renamed, and still being able to load older save files, without much extra work on my part to support them.

    @Marte: Yeah, switching to a text-based save file format is a really good idea, and it’s what I’m intending to do. I haven’t decided whether to use something like XML or a simpler text format matching most of my current data files (possibly then zipped or gzipped, to compensate for the larger file size of text); I’ll have to think about this. But both MMORPG Tycoon 1.0 and 1.1 had binary save files which were extremely non-human-readable.. and I really don’t want to do that again.

  5. Marte says:

    How do you think to manage changing of saving format?

  6. trevor says:

    @Marte: The basic idea is to have each bit of data on an object be identified by a text string. That way, if the data is in an unexpected order in a save file, or if some pieces are missing or extra unknown data is in the file, the game can recognise that and handle the situation nicely; extra data in the save file can automatically be ignored, data missing from the save file will “load” a default value, etc. This gives lots of flexibility for save file loading, between different versions of the game!

    I have a screenshot showing a part of this saved data in my latest blog post; if you take a look at that, you should get a good idea of how all this will work.