Skip to content

Instantly share code, notes, and snippets.

@boformer
Last active January 18, 2023 22:17
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boformer/c3079c976cd121b78d16 to your computer and use it in GitHub Desktop.
Save boformer/c3079c976cd121b78d16 to your computer and use it in GitHub Desktop.
How to load and save data with Cities Skylines' Mod API and Colossal Order's Serialization API
using System.IO;
using ColossalFramework.IO;
using ICities;
using UnityEngine;
/// <summary>
/// A simple example how to save custom data in savegames.
/// This uses 3 components:
///
/// 1. SerializableDataExtensionBase
/// This class is provided by the Mod API to load and save raw byte data
/// from mods in savegames
/// 2. DataSerializer
/// This helper is part of the ColossalFramework, not of the Mod API.
/// It helps you convert single objects or array of objects to bytes.
/// 3. IDataContainer
/// This interface of ColossalFramework must be implemented by the objects
/// you want to serialize.
/// One method must be implemented for serializing, one for deserializing.
/// </summary>
public class BuildingDataManager : SerializableDataExtensionBase
{
// this is the array that contains the extra data for all buildings
// You can access data like this:
/*
BuildingData data = BuildingDataManager.buildingData?[buildingId];
if (data != null)
{
// do stuff with data
}
*/
public static BuildingData[] buildingData;
// The key for our data in the savegame
public const string DataId = "PRCIO";
// Version of data save format
// This is important when you add new fields to BuildingData
// You can start with 0
public const uint DataVersion = 2;
public override void OnCreated(ISerializableData serializableData)
{
base.OnCreated(serializableData);
// Create new empty data array (length of the buildings array, ~32k)
buildingData = new BuildingData[BuildingManager.instance.m_buildings.m_size];
}
public override void OnLoadData()
{
base.OnLoadData();
// Get bytes from savegame
byte[] bytes = serializableDataManager.LoadData(DataId);
if (bytes == null) return;
// Convert the bytes to an array of BuildingData objects
using (var stream = new MemoryStream(bytes))
{
buildingData = DataSerializer.DeserializeArray<BuildingData>(stream, DataSerializer.Mode.Memory);
}
Debug.LogFormat("Data loaded (Size in bytes: {0})", bytes.Length);
}
public override void OnSaveData()
{
base.OnSaveData();
byte[] bytes;
// Convert the array of BuildingData objects to bytes
using (var stream = new MemoryStream())
{
DataSerializer.SerializeArray(stream, DataSerializer.Mode.Memory, DataVersion, buildingData);
bytes = stream.ToArray();
}
// Save bytes in savegame
serializableDataManager.SaveData(DataId, bytes);
Debug.LogFormat("Data Saved (Size in bytes: {0})", bytes.Length);
}
public override void OnReleased()
{
base.OnReleased();
// Clear to save memory
buildingData = null;
}
}
/// <summary>
/// The data class that holds the extra data for each building.
/// When you add new fields, change the DataVersion and do version checks in
/// the Serialize/Deserialize methods. That's important to support data
/// that was saved with previous versions of the mod.
/// </summary>
public class BuildingData : IDataContainer
{
public string fieldA;
public int fieldB;
public int fieldCAddedInV1;
public bool fieldDAddedInV2;
public string fieldEAddedInV2;
// This serializes the object (to bytes)
public void Serialize(DataSerializer s)
{
s.WriteSharedString(fieldA);
s.WriteInt32(fieldB);
if (s.version >= 1)
{
s.WriteInt32(fieldCAddedInV1);
}
if (s.version >= 2)
{
s.WriteBool(fieldDAddedInV2);
s.WriteSharedString(fieldEAddedInV2);
}
}
// This reads the object (from bytes)
public void Deserialize(DataSerializer s)
{
fieldA = s.ReadSharedString();
fieldB = s.ReadInt32();
if (s.version >= 1)
{
fieldCAddedInV1 = s.ReadInt32();
}
if (s.version >= 2)
{
fieldDAddedInV2 = s.ReadBool();
fieldEAddedInV2 = s.ReadSharedString();
}
}
public void AfterDeserialize(DataSerializer s) {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment