Skip to content

Persistence

genar edited this page Sep 21, 2023 · 5 revisions

Do you want to convert worlds or single entities to or from JSON/binary and back? No problem! With the persistence package, you can store and reload your world states with little effort and injectable logic.

Note:

  • Single Entity serialization does not support cyclic references and requires custom handling.
  • World serialization can handle cyclic entity references.
  • Can not handle cross-world references since those are literally unresolvable.

Both serializers support (de)serialization with bytes and streams. The binary one also supports the newly introduced IBufferWriter<T> for streaming purposes.

JSON

JSON is the ultimate data exchange format. If you don't know it, you should really catch up. The usage is very very simple and flexible. Take a look at the git-example project or check out the example!

// Initialize the Serializer, and inject custom ones to handle classes or structs in a specific way.
var serializer = new ArchJsonSerializer(new SpriteSerializer{GraphicsDevice = GraphicsDevice}, ...);

var worldJson = serializer.ToJson(_world);   // Serialize your world to a json-string
_world = serializer.FromJson(worldJson);     // Deserialize it from a json-string.

var entityJson = serializer.ToJson(_world, someEntity);  // Serialize single Entity to json.
serializer.FromJson(_world, entityJson);         // Entity is being deserialized to the given world. 

// Example Custom Serializer for Sprites
public class SpriteSerializer : IJsonFormatter<Sprite>
{
    public void Serialize(ref JsonWriter writer, Sprite value, IJsonFormatterResolver formatterResolver)
    {
        ...
    }

    public Sprite Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
    {
        ...
    }
}

Since the package uses UTF8Json under the hood, you can easily extend it at any time. For an insight into how to create custom serializers, check out the project!

Binary

Binary is fast and efficient. However, not human readable. For certain purposes, it is nevertheless perfect.

// Initialize the Serializer, and inject custom ones to handle classes or structs in a specific way.
var serializer = new ArchBinarySerializer(new SpriteSerializer{GraphicsDevice = GraphicsDevice}, ...);

var worldBytes = serializer.Serialize(_world);   // Serialize your world to a byte[]
_world = serializer.Deserialize(worldBytes );    // Deserialize it from a byte[].

var entityBytes = serializer.Serialize(_world, someEntity);  // Serialize single Entity to byte[].
serializer.Deserialize(_world, entityBytes);                 // Entity is being deserialized to the given world. 

// Example Custom Serializer for Sprites
public class SpriteSerializer : IMessagePackFormatter<Sprite>
{
    public void Serialize(ref MessagePackWriter writer, Sprite value, MessagePackSerializerOptions options)
    {
        ...
    }

    public Sprite Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        ...
    }
}

Since the package uses Messagepack under the hood, you can easily extend it at any time. For an insight into how to create custom serializers, check out the project!

Clone this wiki locally