Savegame design idea

I’m working on the design of my game. I want to minimize the time I spend reading/writing savegames. (Writing a XML-based scheme is something I’m not hoping to do next.) Here is what I think about doing, I’d like to hear whether there is a more Panda-esque way to go.

The game is a virtual tabletop game, the nearest known game would be Medieval II (or showgun Total War), and the virtual board engine VASSAL (http://www.vassalengine.org/community/index.php). Each unit at the moment, and for v1 for sure, will be generic flat boxes representing unit footprints.

Each units have a number of attributes and methods which do not fit really into the Node class (maybe all as tags, but I don’t think that this is a very good design). So what I think of doing is to subordinate the model to instance of units. For serializing the game (at least while in development), I am thinking of:

1- Replacing the pointers to NodePath in the respectives model attributes with a full scene graph path (string)
2 - Write the whole gaming pieces subgraph to a BAM file.
3 - Pickle all the the game logic data.
4 - Bundle both the BAM and the pickled logic into a single file (maybe).
5 - Write a separate terrain/world BAM file.
To Load:

1- Split the BAM file and the pickled logic (if needed).
2- Unpickle the game logic
3- Load the terrain/world BAM
4- Load the BAM into the scene graph
5- reconnect all the pointers to node path using the string path to the nodes.

I know that pickling can be a problem for security, but pickled strings can be encrypted when needed.

I wish that I could just save the game logic states into the Node and save as BAM, but I have the feeling that this wouldn’t work for a reason or another.

Any thoughts?

Thanks,

Christian

Note that you can actually write to a bam file pointers to individual nodes that are nested deeply within a scene graph–you don’t have to write out the NodePath string name and then find it again.

To do this, use the BamFile class. You would first write out the entire scene graph, and then you would write out individual nodes, one at a time. Use the BamFile.writeObject() interface to write out each node, something like this:

bf = BamFile()
bf.openWrite(Filename('myfile.boo'))
bf.writeObject(sceneRoot.node())

And then iterate through all of your node objects, and write them out too:

bf.writeObject(thisNode.node())
bf.writeObject(thatNode.node())

When you read it back in, use the BamFile.readNode() interface to read back your nodes. Be sure to call readNode() exactly the same number of times you called writeObject(), and in the same order. Something like this:

bf = BamFile()
bf.openRead(Filename('myfile.boo'))
sceneRoot = NodePath(bf.readNode())
thisNode = NodePath(bf.readNode())
thatNode = NodePath(bf.readNode())

You can name the file whatever you like, of course. In the above example, I gave this file the extension of .boo, in accordance with Panda’s convention: .bam (stands for “Binary Animation and Models”) is the extension when the file contains just a single scene graph root, while .boo (“Binary Other Objects”) is the extension when the file contains multiple nodes or objects of different types.

You’ll still need to use pickle to store your Python objects in a separate file, of course.

David

Thanks,

It is good to know about BAMfile; it can come handy.

I was browsing the Reference and found PandaNode::setPythonTag(). This is great because it solve my problem of associating Nodes and their python game logic data class. However, this doesn’t get written to a BAM file.

 Would it be possible to write to a BAM file the pickled version of a PythonTag value as a regular string tag? I wouldn't expect the pointers in these objects to work as expected, and this may be a show-stopper, but this possibility is worth thinking about.

Cheers,

Christian

You can certainly put a pickled string in the setTag() field, which does get written to the bam stream. Of course, it is then your responsibility to unpickle it upon load. But, sure, this can be a handy way to insert your entire pickle data into the bam file: you could just store it as a tag on the root node.

David

Oh, let me comment about this:

Encrypting a pickle stream does absolutely nothing in terms of security. Anyone who has access to your program (that is, anyone who can run your program) also has access to the encryption key, since that has to be built into the program. Therefore, a hacker can still insert malicious data into the pickle stream, even if you encrypt it. It doesn’t matter how strong the encryption is. If your program knows how to encrypt and decrypt the stream, so does a hacker.

Of course, none of that matters in the slightest. A hacker could just insert malicious data into the program itself, so worrying about the pickle stream is kind of silly.

The security problems with pickle aren’t an issue when you’re talking about programs and data running entirely self-contained on the user’s machine.

The thing to watch out for is that you don’t run a pickle stream that could have come from some other source. For instance, you shouldn’t write a program that loads pickle streams from some website outside of your control: this program could easily install malicious code onto an unsuspecting user’s computer. But as long as the program in question is just loading pickle files that the program itself has written out–and there’s no way for an outsider to the computer to insert a malicious file in its place–there’s no particular danger in using pickle.

David

bongo, i think you are going about this the wrong way.

Why are you saving the model files??? The model files are included with the game and should be as data of the game not the saved game file. No need to save the things into your own file. Your own file should just contain the attributes of a map and attributes and positions of your units. Pickle could work great with this. As well as any other format like jason or xml.

If you require storing multiple files for what ever reason just write them to a directory and zip it up when you are done… python provides planty of intefaces for writing/reading zips and panda provides plenty of interfaces to multifiles …

You may be right: that saving the models isn’t necessary (especially since I don’t plan to generate any procedurally at runtime).

OK, so how can I define the state of the node: getAttrib, getTransform, get all Tags somehow. Is there a quick way to obtain all non-model data for a node? getState() maybe? The reference docs aren’t clear on this.

Hi bongo,

I have not implemented this feature in my game/demo but my
idea is delegate the load and save operation to my managers;
object manager, room manager, actor manager. They in turn will
delegate to every instance of objects. So, in the end the idea is to
serialize / de-serialize to a file the state of the objects.
I hope this help.
Regards.
Alberto