Modding:Serialization (Saving/Loading)

What is Serialization?
Serialization is how games and other programs convert data (in Qud's case, C# class fields) into a format that can be written to a file, so that it can be stored between sessions. Effectively, it's how a game saves its data. The opposite process, the process of loading data from a file, is called deserialization.

There are many different ways that data can be (de)serialized. One particular format that Qud uses for its persistent data files is XML. One advantage of XML is that the data can be read by the game independent of the game version, however, it also takes up more storage space. Another consideration is that it makes the data human-readable and -editable, which is useful for modding.

Qud uses binary blobs for save data. The format is not easily readable or editable by humans, but it is highly flexible in programming terms and can be used for a wide variety of data. However, to some extent it also relies on certain things not changing across game and mod versions, so it can be easily invalidated by certain types of changes.

Due to the modular way in which Qud does serialization, as a mod author you don't have to concern yourself with all the specifics of the save format. The remainder of this article describes how to use the tools that Qud and its engine provide for telling it how you would like to serialize your mod data.

How Serialization Works for Qud
This section assumes you have the following  directives at the top of your code, which tell C# where to find the attributes you will be using:

In many cases, you can simply include the the  attribute at the top of your class definition, and Qud's game engine will take care of serializing all of your   class fields for you. Specifically, Qud is capable of correctly serializing all intrinsic types (such as,  , etc.) as well as containers of those types (such as  ). If your class only uses intrinsic types, the  attribute should be all that you need. Qud will properly save and load your data without further effort. Note that,  , and   class fields are not serialized by default. If you want the values associated with private or protected class fields to be retained through a save and load, you need to mark each individual private or protected field with a  attribute. Static fields cannot be serialized in this manner. See the Unity docs for more information about serializable fields (note that the GameObject discussed on that linked page is not related to the GameObject type commonly used in Qud).

Here is an example of the basic concepts discussed above:

Object fields are not serialized automatically. If your class introduces a new field for an object type or a container of objects, such as a GameObject field that stores a reference to some particular object, a List that stores a list of liquid volumes, or a completely new type of object introduced by your mod, you must implement custom serialization for those object fields, or your object references will no longer be valid after the game is reloaded.

However, if your class extends a built-in class, such as, object fields from the built-in class will already have the required custom serialization logic (typically implemented in their Save/Load or SaveData/LoadData functions). For example, IPart contains the field, which stores a reference to the GameObject that the part is a component of. contains the special logic necessary to serialize that GameObject when the game is saved, and  contains the logic required to deserialize that object so that it remains valid after a player reloads that save. This means that if your class extends IPart, you can safely rely on the fact that references to the parent object, such as, will always be valid in your code.

If you can find a way to reference objects in your code without explicitly saving a reference to those objects in a new field, it's generally a good idea to avoid creating that field so you don't have to serialize it. For example, there's pretty much always a convenient way to retrieve a reference to the GameObject that your part is attached to, or a reference to the Player object, without saving those objects in your own discrete fields.

Custom Serialization
As described above, Qud's default serialization is not sufficient for object fields introduced by your custom classes. In those cases, you need to tell the game to let you serialize a field yourself. By putting the attribute [NonSerialized] above a field, it tells the game not to save that field. You can then add your own custom save behavior.

If your class extends IPart or Effect, you should override the  and   methods to handle your custom serialization. These are the only virtual methods the game currently makes available for serialization. If you need to serialize data outside of a class that extends IPart or Effect, you will need to look at the  and   classes and implement your own serialization logic.

Qud does provide some serialization helper functions. In particular, serializing GameObject fields or lists is particularly easy if you use the  or   functions. Here's an example straight from the game that shows how Qud serializes a character's inventory, which is stored as a list of GameObjects in the  class: Below is an additional example segment of code with comments that shows how you might serialize a custom list.

There may be other instances where you need custom serialization. The methods shown above can be applied to other situations as well.