Warman no usa JSON, XML, Protobuf ni ninguna libreria de serializacion de terceros. Cada pieza de datos que se escribe a disco o se envia por la red usa un formato binario personalizado construido sobre BinaryReader y BinaryWriter de C#. Esto incluye archivos de guardado, datos de sala, puntos de terreno, ticks de red, datos de objetos y contenido de mods.

El Interfaz

Todo el sistema se basa en un interfaz: IBinarySerializable. Tiene dos metodos: WriteBytes(BinaryWriter) y ReadBytes(BinaryReader). Cualquier struct o clase que implemente este interfaz puede serializarse a un array de bytes y deserializarse de vuelta.

Struct in memory .ToBytes() BinaryWriter field by field byte[ ] byte[] 7 bytes typical network or disk BinaryReader field by field FromBytes() == identical
Serializacion binaria: struct a bytes y vuelta, sin reflexion

Metodos de Extension

La clase BinaryExtension proporciona metodos de extension para tipos de Unity (Vector3, Quaternion, Bounds), enums del juego (DamageType, EffectType, ItemRarity), arrays, listas, tipos nullable y referencias de assets. Escribir un Vector3 son tres floats. Escribir un enum es un solo byte.

Las referencias de assets (como modificadores, presets de enemigos y archivos de sala) se serializan por nombre. Al escribir, se almacena el string del nombre del asset. Al leer, el nombre se busca en un registro global de assets. Esto significa que los archivos de guardado contienen nombres string para assets, no punteros binarios, asi que sobreviven actualizaciones del juego que cambien los layouts de memoria.

Por Que No JSON?

Tres razones. Primero, tamano: un PlayerInputCommand serializa a unos 7 bytes en binario. Los mismos datos como JSON serian 10-20x mas grandes. Segundo, velocidad: lectura/escritura binaria son operaciones de memoria directas, sin parsing necesario.

Versionado

La contrapartida es el versionado. Los formatos binarios se rompen cuando cambia la forma de los datos. Warman lo resuelve con bytes de version al inicio de las estructuras de datos criticas. Un TerrainPoint escribe su version (actualmente 1) como primer byte. El lector comprueba la version y ramifica al camino de deserializacion correcto.