[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Adonthell-devel] Game saving
From: |
Kai Sterker |
Subject: |
Re: [Adonthell-devel] Game saving |
Date: |
Sun, 02 Dec 2001 21:42:19 +0100 (CET) |
On Sun, 02 Dec 2001 13:24:12 -0700 Lakin Wecker wrote
> On December 2, 2001 04:43 am, you wrote:
>> I had some more thoughts on this matter, so here is my suggestion:
>>
>> According to that design pattern
>> (http://rampages.onramp.net/~huston/dp/MementoDemos.cpp), each class that
>> has to be state-saved needs a "data_class" that will hold all the data in
>> need of saving. The only thing our class does on saving is to return the
>> data-class properly filled.
>
> Correct.
>
>> Here's the first change I suggest: instead of using normal variables in
>> the data_class, why not store everything as key/value pairs?
>
> Sounds good.
>
>>Assuming
>> we only have ints and strings to save it would not be a problem.
>
> Why not other data types? (see explanation below)
>
>> One question is what happens with complex data, like a map that contains
>> various submaps, or a character that contains an inventory.
>
> The approach I would take would be to define a class called say Any (or use
> one that is already available: http://www.boost.org/libs/any/index.html).
> This is a class which can hold any type of variable that you want, so it
> works with Integers, Strings, Lists, Maps, etc. It dynamically figures out
> what it holds, and has all the proper overloaded operators, and copy
> constructor functions. So it acts like any normal type.
> Example:
>
> Any myValue = 1; // you now have an integer
> if(myValue == 1) //is true...
>
> myValue = "myName"; // you now have a string
> if(myValue==1) //is false.
>
> std::map<string, string> myMap;
> //add values and keys to myMap.
> myValue = myMap; // you now have a map.
>
> etc... etc..
>
> so in your base_data("memento class") you have a
> std::map<string, any> myValues;
>
> The saveToFile function can convert the the map to a format which is
> represented by a string or we could write some utility functions to do that.
> I would serve to have a standard format to convert an "any" value to a
> string. That way an "any" value could be streamed over a socket to
> communicate between server and client.
>
> The formats I would suggest would be python format and/or Bach format.
>
> The tricky parts about this are the actual converting something to a string,
> and back again.
> It requires a bit of tricky input and output code, including a few stacks
> etc. Regardless, I think it would serve well here.
>
>> So you had for example:
>>
>> // save character
>> base_data *data = my_character->save ();
>> data->save (file);
>
> If done properly with an any class, and some simple recursion to make sure
> you get everything, the above code would save the entire character and his
> inventory to a file.
>
>> I think the benefit of this is that all the actual saving code of all
>> classes we want to save is grouped at one point. It further is flattened,
>> so you no longer have method calls through several classes in order to
>> save a complex object, which helps preventing coding errors.
>
>> Actual file access happens in one class only, so we can easily react to
>> I/O-Errors and such.
>
> Agreed.
> As Kai pointed out the "Database" layer should be seperate from the program
> so that it is transparent. So if for some strange reason you decided to
> being storing savegames and stuff in MySQL it would be possible(i don't
> recommend this, it's just the principle. ;P )
>
>> And why store everything as key/value pairs? Right now, if the savegame is
>> not recent we most likely crash. Any change to the format will make it
>> incompatible with prior versions.
>> With the key/value pairs however, removing data from a savegame won't
>> render old savegames invalid. The superflouos pair will simply be ignored.
>> (We can do that now as well, but it means keeping obsolete code in the
>> load function).
>> Adding data to the savegame is a bigger problem. At least we can detect
>> that data is missing (instead of reading wrong data), and maybe we can
>> even substitute a default value for not so critical data to remain
>> compatible.
>> Even if we can't, writing a save game converter is not hard, as it needs
>> not to know the structure of each object in the file. It just needs to
>> know the part to be modified. If we add additional control information to
>> the file, finding and modifying all items in a save game is quite simple.
>> With a binary save file, it's much harder.
>
> Here are my views of the saving/loading functions and classes.
>
> 1) They should have distinctive versions.
Certainly. The current files already contain version numbers but the
underlying code is bad, as updating the number requires changes at several
points ;P. If that would be done properly, it'd be just a matter of
discipline.
> 2) Each version should have a python script(or two) with these uses.
> a) Converting to this version which includes removing
> Superfluous lines and data that isn't needed, and Adding
> Default keys and default values when missing.
Where possible this is a good idea. But there might be occasions where
assigning a default value hasn't the desired effect.
> b) Integerity Checking of a savefile.
Definately. I forgot about that this morning, but one advantage of
concentrating all disk operations at a single point is that we can easily
calculate a checksum for integrity checks. File corruption could still
crash the program otherwise. (As a side effect, it makes cheating harder
too.)
> c) i feel that because you already have python scripting this script
> could also be used to actually save and load the game. This
> would not only allow for on the fly conversion, but would save us
> the tricky bit about string parsing and handling in C++.
That's worth a thought.
> I don't think it will. Using bz2 to compress it while we write it to the
> file would be also work to save on file size.
We use zlib right now, which should be just as good. (Though bz2 might
have a slightly better compression.)
> Even if it does add a little time to the loading and saving of the game, it
> would be nice to have the integrity checks, and converting information
> available. I think players will forget extra half seconds spent loading the
> game when cirrus dazzles them with his graphics, but they _will_ remember a
> segfault. :)
True. As long as it's "reasonably" fast. Don't know if you played Gothic;
you could cook coffee during game loading ;).
Kai
- [Adonthell-devel] Game saving, Kai Sterker, 2001/12/02
- Re: [Adonthell-devel] Game saving, Lakin Wecker, 2001/12/02
- Re: [Adonthell-devel] Game saving,
Kai Sterker <=
- Re: [Adonthell-devel] Game saving, Kai Sterker, 2001/12/03
- Re: [Adonthell-devel] Game saving, Lakin Wecker, 2001/12/04
- Re: [Adonthell-devel] Game saving, Alexandre Courbot, 2001/12/04
- Re: [Adonthell-devel] Game saving, Kai Sterker, 2001/12/04
- Re: [Adonthell-devel] Game saving, Alexandre Courbot, 2001/12/08
- Re: [Adonthell-devel] Game saving, Kai Sterker, 2001/12/08
- Re: [Adonthell-devel] Game saving, Kai Sterker, 2001/12/08