The first stage in determining how to structure your save-file is determining what information needs to be stored. Presumably, you have a list of entities, each of which with generic information (probably derived from one of a few base classes), such as position, velocity etc.
One of the best things you can do to implement a map format is to have a save-parser for each class (some can just derive from the base class' save-parser). So for instance, if you have a player class, which derives from CBaseNPC, you could most-likely simply derive from CBaseNPC, override the parser, calling the base-class function, and adding any other necessary fields, for example, if we had (pseudocode):
void CBaseNPC::Save() {
SaveToFile( health );
SaveToFile( armor );
SaveToFile( weapons );
SaveToFile( position );
SaveToFile( angles );
}
Then for your player class:
void CPlayer::Save() {
CBaseNPC::Save();
SaveToFile( achievement_progress );
}
Obviously, this is just a simple example, and no doubt your saving parsers will have more fields etc. to deal with.
Dealing with the structure of the file itself, the main thing you need to worry about is delimiters, how will your main load-parser recognise what each field corresponds to?
I suppose the best way to explain this would be with an example, the following could be a simple start to a save-file:
Map: {mapname}
Gametime: {gametime}
===Player===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
AchievementProgress: {arbritraryData}
===Player===
===NPC-npc_name===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
===NPC-npc_name===
===Entity-item_name===
Position: {x, y, z}
Angles: {yaw, pitch, roll}
Model: {modelname}
===Entity-item_name===
Here we have used the "===" string as a delimiter for the start of a class's parameters, and a new line as the delimiter for the parameters within each class.
It is then a relatively simple matter of structuring your parser so it reads in the map name, and loads it. Then sets the game-time to the value specified in the save-file.
It then looks through the file until it finds a "===" reads the string it encounters, and looks it up from a dictionary (possibly an std::map
or std::unordered_map
) to determine the class to create (or edit) with the information in the file. Once it has determined the class type, it can then proceed to call the Load()
function from that class, which will retrieve all the information contained. The parser then looks for the next instance of the "==={string encountered}===" and closes that class. It then proceeds following the same procedure with the next class encountered.
Sorry for the length of this post, and I'm sure it could be made briefer and there are probably some things I have missed, I just wrote this off the top of my head, so there may be erroneous things here, but I hope it puts you on the right path to getting a workable save-file format. :)
If you still have any problems or questions regarding my post, please comment, I'll do my best to answer promptly.