Modding:Serialization (Saving/Loading): Difference between revisions

Jump to navigation Jump to search
m
Woopsed namespace end brace
m (a bit more detail)
m (Woopsed namespace end brace)
 
(13 intermediate revisions by 4 users not shown)
Line 1: Line 1:
[[Category:Modding]]{{Modding Info}}
{{Modding Info}}{{Modding Topic Prerequisites | Modding:C Sharp Scripting}}[[Category:Script Modding]]
 
== What is Serialization? ==
== What is Serialization? ==
Serialization is how games and other programs convert data ''(specifically, C# class fields)'' into a file format, so that it can be stored between sessions. In simpler terms, it's how a game saves its data. The process of loading data from a file is called "Deserialization".


There are many different ways data can be de/serialized, for example, Qud's xml files are a way of storing data in a formatted fashion. The advantage of this is that this data works independent of game versions, however, it also takes up much more storage space. This also makes the data human readable/editable, which is useful for modding, but could allow for save editing if used for game data.
''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.


These reasons are why Qud uses an unformatted save format. In this format, the game simply saves the raw data of in-game objects with only enough information necessary to load the data back into the game. This data takes up less space, and cannot easily be manipulated by players, but is not compatible between game/mod versions.
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 ==
== How Serialization Works for Qud ==
In many cases, you can simply include the the <code>[Serializable]</code> attribute at the top of your class definition, and Qud's game engine will take care of serializing all of your <code>public</code> class fields for you. Specifically, Qud is capable or correctly serializing all intrinsic types (such as <code>string</code>, <code>int</code>, etc.) as well as containers of those types (such as <code>List<string></code>). If your class only uses intrinsic types, the <code>[Serializable]</code> attribute should be all that you need. Qud will properly save and load your data without further effort. Note that <code>private</code>, <code>protected</code>, and <code>static</code> 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 <code>[SerializeField]</code> attribute. Static fields can never be serialized. See [https://docs.unity3d.com/ScriptReference/SerializeField.html 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:<syntaxhighlight lang="c#">
This section assumes you have the following <code>using</code> directives at the top of your code, which tell C# where to find the attributes you will be using:
 
<syntaxhighlight lang="C#">
using System;
using SerializeField = UnityEngine.SerializeField;
</syntaxhighlight>
 
In many cases, you can simply include the the <code>[Serializable]</code> attribute at the top of your class definition, and Qud's game engine will take care of serializing all of your <code>public</code> class fields for you. Specifically, Qud is capable of correctly serializing all intrinsic types (such as <code>string</code>, <code>int</code>, etc.) as well as containers of those types (such as <code>List<string></code>). If your class only uses intrinsic types, the <code>[Serializable]</code> attribute should be all that you need. Qud will properly save and load your data without further effort. Note that <code>private</code>, <code>protected</code>, and <code>static</code> 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 <code>[SerializeField]</code> attribute. Static fields cannot be serialized in this manner. See [https://docs.unity3d.com/ScriptReference/SerializeField.html 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:
 
<syntaxhighlight lang="c#">
using System;
using SerializeField = UnityEngine.SerializeField;
 
namespace XRL.World.Parts
namespace XRL.World.Parts
{
{
Line 27: Line 44:
         }
         }
     }
     }
}
</syntaxhighlight>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<LiquidVolume> 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.
</syntaxhighlight>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<LiquidVolume> 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.


Line 66: Line 84:
}
}
}
}
</syntaxhighlight>Below is an additional example segment of code with comments that shows how you might serialize a custom list.<syntaxhighlight lang="csharp">
</syntaxhighlight>
Below is an additional example segment of code with comments that shows how you might serialize a custom list.
{{Missing info|The code below assumes that <code>StandAbility</code> has implemented a meaningful Save method when it calls <code>ability.Save(Writer)</code>. It's not really a complete example.}}
<syntaxhighlight lang="csharp">
...
...
         // The non-serialized attribute signals not to save this list when SaveData is called.
         // The non-serialized attribute signals not to save this list when SaveData is called.
Line 106: Line 127:


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

Navigation menu