Skip to content

Serialization / Savings

Persistence.Serialize and Persistence.Deserialize is replaced with GenericPersistence class

Example of how to persist a custom system.

namespace Server.ExampleSystem
{
    public static class ExampleSerialization
    {
        public static void Configure()
        {
            GenericPersistence.Register("ExampleSystem", Serialize, Deserialize);
        }

        public static void Serialize(IGenericWriter writer)
        {
            // Do serialization here
            writer.WriteEncodedInt(0); // version
        }

        public static void Deserialize(IGenericReader reader)
        {
            // Do deserialization here
            var version = reader.ReadEncodedInt();
        }
    }
}

Basic info

ModernUO can programatically generate migrations. This feature is based on internal C# Source generators More info

Old way of serializing objects:

public class ExampleItem : Item
{
  public string ExampleText { get; set; }

  [Constructible]
  public ExampleItem() : base(0)
  {

  }
  public ExampleItem(Serial serial) : base(serial)
  {
  }

  public override void Serialize(IGenericWriter writer)
  {
      base.Serialize(writer);

      writer.WriteEncodedInt(0); //Version
      writer.Write(ExampleText);
  }

  public override void Deserialize(IGenericReader reader)
  {
      base.Deserialize(reader);

      var version = reader.ReadEncodedInt();
      ExampleText = reader.ReadString();
  }
}

Same class serialized with codegen

[Serializable(0)]
public partial class ExampleItem : Item
{
  [SerializableField(0)]
  public string ExampleText { get; set; }

  [Constructible]
  public ExampleItem() : base(0)
  {

  }
}

Step by step

  1. Add SerializableAttribute(versionNumber) to your class and make it partial
    [Serializable(0)]
    public partial class ExampleItem : Item
    
  2. Delete constructors with Serial serial, Serialize and Deserialize methods.
  3. Add SerializableField(fieldOrder) attribute to all field you want to serialize.
    [SerializableField(0)]
    public string ExampleText { get; set; }
    
  4. Build project "Run Schema Migrations". ModernUO will create migration files for you. In this case "Server.Items.ExampleItem.v0.json" and "Server.Items.ExampleItem.Serialization.cs" These files contains all information and classes needed for MUO to serialize/deserialize your objects.

Migrations

When new field is added to serialization, you need to increment versionNumber and make migration files. Here is little example.

New class code will look like this:

[Serializable(1)]
public partial class ExampleItem : Item
{
  [SerializableField(0)]
  public string ExampleText { get; set; }

  [SerializableField(1)]
  public string AddedExampleTest { get; set; }

  [Constructible]
  public ExampleItem() : base(0)
  {
  }
}

After building "Run Schema Migrations" project, MUO will generate V0Content in serialization class.

This Content contains all fields from V0. Now create MigrateFrom for each version you make, in this case V0.

Tip

When you have more versions, create standalone file for migrations only. For example "ExampleItem.Migrations.cs"

private void MigrateFrom(V0Content content)
{
    ExampleText = content.ExampleText;
}

Your migration is now completed.

Migrating from pre-codegen

For migration from pre-codegen code, use method

private void Deserialize(IGenericReader reader, int version)

this method is called when codegen doesnt have VXContent for deserialized object or version of Content is lower than deserialized. In this method you can make old fashioned deserialization as before codegen.

After deserialization

For some code changes after world load, you can use AfterDeserializationAttribute.

[AfterDeserialization]
private void AfterDeserialization()
{
  // Some code here
}

Embedded serialization

Sometimes you need to serialize object inside object. For this you should use "EmbeddedSerializableAttribute". Nice example to understand it is "AquariumState"