Table of Contents

Namespace Core.SaveLoad

Classes

CustomSystemSerializers

ENGINE LAYER - Custom serialization logic for specific systems

Purpose: Some systems (TimeManager, ResourceSystem) have custom serialization needs that don't fit the generic SaveState/LoadState pattern.

This class centralizes that custom logic, keeping SaveManager clean.

Systems with generic SaveState/LoadState:

  • ProvinceSystem, ModifierSystem, CountrySystem, UnitSystem (These use SystemSerializer directly, no custom logic needed)

Systems with custom serialization:

  • TimeManager (multiple fields, not a single SaveState method)
  • ResourceSystem (iterates all resources, special capacity handling)
SaveFileSerializer

ENGINE LAYER - Binary save file format serializer

File Format v2:

  • Magic bytes: "HGSV" (4 bytes)
  • Format version: int32 (4 bytes) — 1 = legacy, 2 = metadata+compression
  • Metadata header: 256 bytes (fixed-size, readable without full deserialization)
  • Compressed payload (GZip):
    • System data: count + (name, length, bytes) pairs
    • Command log: count + bytes[]
  • Checksum: uint32 (CRC32 of compressed payload)

File Format v1 (legacy):

  • Magic bytes: "HGSV" (4 bytes)
  • Header: variable-length metadata
  • System data + Command log (uncompressed)
  • Checksum: uint32
SaveGameData

ENGINE LAYER - Container for all save game data

Architecture:

  • Generic container, systems populate their own sections
  • Metadata for version compatibility and UI display
  • State snapshot for fast loading
  • Command log for determinism verification

Usage: SaveManager creates this, passes to systems via OnSave() Systems populate their data sections SaveManager serializes to disk

SaveManager

ENGINE LAYER - Orchestrates save/load operations across all systems

Responsibilities:

  • Coordinate OnSave/OnLoad calls to all systems (via SystemRegistry)
  • Serialize/deserialize SaveGameData to disk (binary format)
  • Manage save file paths and naming
  • Atomic writes (temp file → rename to prevent corruption)
  • Version compatibility checks

Architecture:

  • Pure orchestrator, doesn't own game state
  • Systems serialize their own data via OnSave/OnLoad
  • Dependency order handled by SystemRegistry
  • GAME layer hooks OnPostLoadFinalize for game-specific finalization

Usage: saveManager.SaveGame("my_save"); saveManager.LoadGame("my_save"); saveManager.QuickSave();

SerializationHelper

ENGINE LAYER - Low-level binary serialization utilities

Principles:

  • Deterministic serialization (same data = same bytes)
  • Platform-independent (works on Windows/Mac/Linux)
  • Efficient binary format (no JSON/XML overhead)
  • Type-safe helpers for common patterns

Handles:

  • FixedPoint64 (as long RawValue for determinism)
  • NativeArray (raw memory copy)
  • Primitives (int, ushort, string, etc.)
  • Arrays of primitives
SystemSerializer

ENGINE LAYER - Generic system serialization helper

Responsibilities:

  • Provide generic Save/Load methods for systems with SaveState/LoadState
  • Handle MemoryStream/BinaryWriter/BinaryReader boilerplate
  • Store/retrieve serialized data in SaveGameData
  • Reduce SaveManager code duplication

Pattern: Instead of writing 6+ pairs of SaveXXX/LoadXXX methods with identical patterns, use generic methods that work with any system implementing the save/load pattern.

Usage: systemSerializer.SaveSystem(saveData, "TimeManager", gameState.Time); systemSerializer.LoadSystem(saveData, "TimeManager", gameState.Time);

Structs

SaveMetadata

Fixed-size metadata header for fast save browser preview. Written at a fixed position in the save file so it can be read without deserializing the entire file. Total size: 256 bytes.