Files
MVP1/Docs/Modules/Save.md
T

7.4 KiB
Raw Blame History

Сохранения

Игровое состояние: запись и загрузка save.json. Модуль не знает, что хранят другие модули: каждый модуль сам отдаёт свою секцию.

  • Сборка: Bogatyri.Save.
  • Папка: Assets/Scripts/Modules/Save.
  • Зависит от: ядра.

Контракт ISaveSystem

Член Что делает
HasSave Есть ли файл сохранения.
SaveNow() Сохранить сейчас.
DeleteSave() Только стереть файл (состояние модулей в памяти не меняется).
ResetAll() Сброс сохранений: все модули возвращаются к новой игре, файл сразу перезаписывается.

Для слоя приложения остаются SaveManager.Instance.SaveGame(), LoadGame(), HasSaveFile(), DeleteSave().

Как модуль подключает свои данные

public class MyModule : ISaveParticipant
{
    public string SaveKey => "mymodule";
    public string Capture() => JsonUtility.ToJson(data); // null -- оставить то, что уже в файле
    public void Restore(string json) { data = JsonUtility.FromJson<MyData>(json); }
    public void ResetState() { data = new MyData(); } // новая игра
}
SaveRegistry.Register(myModule); // при запуске модуля
Секция Модуль
economy Экономика
settlement Поселение
world Глобальный мир
circle Круг (простые строки, не JSON — модуль без Unity)
army Армия (простые строки: troops=…, march=…)
population Население (простые строки: civilians=…, lastTick=… и др.)

Формат файла

Версия 2: { "version": 2, "sections": [ { "key": "economy", "json": "..." } ] }.

Версия 1 (старый плоский save.json) читается сама: файл целиком отдаётся Экономике и Поселению, их секции берут поля по старым именам.

Когда сохраняется

  • Автоматически:
    • автосохранение каждые 30 секунд;
    • при сворачивании и закрытии игры;
    • перед переходом между сценами (SceneNavigator);
    • после событий походов.
  • Защиты:
    • пока сохранение не загружено, запись пропускается — иначе стартовые нули модулей затёрли бы файл;
    • секция модуля, которого сейчас нет (например, город на карте мира), не пропадает.

Сброс сохранений

Откуда Что происходит
Настройки → «Сбросить весь прогресс» GameProgress.ResetAll(): удаляет progress.json, вызывает ISaveSystem.ResetAll(), создаёт новый прогресс (герой, задания, почта, войска).
ISaveSystem.ResetAll() Стирает save.json, вызывает ResetState() у каждого модуля, сразу записывает новую игру, публикует GameResetEvent.
Tools → Сбросить сохранения (редактор) В Play Mode — то же, что кнопка в Настройках. Вне Play Mode — удаляет save.json и progress.json.
Tools → Открыть папку сохранений Открывает Application.persistentDataPath.

Что сбрасывает каждый модуль:

  • Экономика — стартовые ресурсы из Inspector ResourceManager;
  • Поселение — Ратуша 1 уровня, постройки убраны, участки свободны;
  • Мир — все походы отменены;
  • Круг — игрок ни в каком Круге, его Круги распущены;
  • Армия — войск и походов нет;
  • Население — стартовый город (270 жителей). После сброса App/GameModules выдаёт стартовое войско и ресурсы из EconomyConfig.

Новый модуль с данными обязан реализовать ResetState(), иначе он не скомпилируется: метод входит в контракт.

События

Публикует:

  • GameLoadedEvent — после загрузки (и когда файла сохранения нет — загрузка завершена, новая игра);
  • GameSavedEvent — после записи;
  • GameResetEvent — после сброса сохранений;
  • NewGameStartedEvent — GameBootstrap: файла сохранения нет, первая игра на устройстве.

Слушает: ничего.

Файлы

Файл Что это
SaveManager.cs Запись и чтение секций, автосохранение, перенос версии 1.
GameBootstrap.cs Загружает сохранение при старте сцены города.
Assets/Editor/SaveResetMenu.cs (редактор) Меню Tools → Сбросить сохранения / Открыть папку сохранений.

Решения и план

  • Этап 0: одно сохранение. GameProgress (progress.json: герой, задания, почта, магазин, арена) пока пишет свой файл. Его данные переводятся в секции по мере выноса в модули. Войска уже перенесены — секция army.
  • Номер версии файла поднимать при каждом несовместимом изменении и дописывать перенос старой версии здесь.

Журнал изменений

Дата Кто Что
26.10.2026 Claude Новая секция population (модуль Населения). GameBootstrap публикует NewGameStartedEvent, если файла нет.
23.10.2026 Claude Новая секция army (модуль Армии). GameLoadedEvent публикуется и без файла сохранения.
19.10.2026 Claude Новая секция circle (модуль Круга).
19.10.2026 Claude Сброс сохранений: ISaveSystem.ResetAll(), ResetState() у модулей, GameResetEvent, меню редактора. Кнопка в Настройках теперь сбрасывает и походы, и память Поселения.
19.10.2026 Claude SaveManager переписан на секции модулей (ISaveParticipant), формат v2 с переносом v1. Запись до загрузки запрещена. Сохранение города вынесено в модуль Поселения, походов — в модуль Мира.