# Сохранения: JSON, идентификаторы и восстановление состояния

## Формат и границы

[C7Engine/SaveManager.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/SaveManager.cs) распознаёт SAV, BIQ, JSON и ZIP по расширению. Однако собственный [SaveGame.Save](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/C7GameData/Save/SaveGame.cs) записывает UTF-8 JSON, а `Load` читает файл через `File.ReadAllText`.

В этом пути нет упаковки или распаковки ZIP. Следовательно, признанное расширение `.zip` нельзя объявить поддержкой настоящих ZIP-архивов. Такая несогласованность — хороший пример, зачем проверять обработчик, а не enum формата.

Сериализация использует `System.Text.Json`, отдельные Save-типы, поля и преобразователи. Глубокое копирование ruleset тоже выполняется через JSON. В данных есть поле Version со значением по умолчанию `0.0.0`; это не доказывает наличие полной системы миграций.

## Восстановление ссылок

Преобразование SaveGame в GameData создаёт определения, технологии, игроков, карту, здания, юниты и города в определённом порядке. Ссылки разрешаются по ключам и ID. После загрузки пересчитываются владельцы клеток и инвалидируется торговая сеть.

Это решает проблему циклического графа: город ссылается на жителя, житель на клетку, клетка на город. Сериализовать весь рабочий граф напрямую означало бы получить циклы или дубликаты. Источники: [C7Engine/C7GameData/Save/SaveCity.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/C7GameData/Save/SaveCity.cs), [C7Engine/C7GameData/Save/SaveUnit.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/C7GameData/Save/SaveUnit.cs), [C7Engine/C7GameData/ID.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/C7GameData/ID.cs).

## Режим и случайность

Сохраняется конфигурация игрового режима, история, номер хода, состояние игроков и победы. Поведение загружается заново из режима; итог зависит от установленной версии Lua-файлов.

Сохранён seed. При создании GameData генератор случайности инициализируется через `new Random(seed)`. Из рассмотренного пути не следует сохранение внутреннего состояния RNG или счётчика использованных значений. Один seed не гарантирует идентичное продолжение после загрузки.

Источник: [C7Engine/C7GameData/GameData.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/C7Engine/C7GameData/GameData.cs). Для нашей игры это основание хранить состояние собственного PRNG и различать случайность генерации карты, боя и AI.

## Документация и код расходятся

[Technical notes](https://github.com/C7-Game/OpenCiv3/wiki/Technical-notes) обсуждает проблемы циклов и историческое предложение перейти на Newtonsoft во времена .NET 6. Текущий SaveGame использует System.Text.Json; предложение не следует выдавать за актуальную зависимость сериализации.

## Применение к нашему экспорту

Наш `version: 1` и localStorage уже полезны, но профиль следует дополнить версией схемы, идентификатором правил, версиями ресурсов, PRNG и фазой хода. Проверять уникальность ID и целостность ссылок до изменения текущей партии.

Ключевой сценарий: сохранить после частичного хода, загрузить и продолжить без повторного производства, повторного хода AI или потери договоров. [EngineTests/GameData/SaveTest.cs](https://github.com/C7-Game/OpenCiv3/blob/c1370e2f63a6042a3c4206f0043543d7da0d5cc5/EngineTests/GameData/SaveTest.cs) содержит исходники round-trip и других проверок; здесь тесты не запускались.

