Files
MVP1/Docs/Modules/Save.md
T
AlexanderandClaude Opus 5.5 ae9c141b49 Ресурсные точки на карте мира (регламент 31.10, наша часть по решению №46)
Мир (Bogatyri.World.Simulation, WorldSimulation.Points.cs):
- точки дерева, камня, металла, золота трёх размеров; запас, добыча воина за игровой час
  (1 игровой час = 5 реальных минут), груз на воина, срок жизни 12/24/48 реальных часов — ТЕСТ
- сбор: дошли → стоят на точке (MarchState.Gathering) до полного груза, истощения или исчезновения точки,
  затем физический возврат с грузом; всё считается в момент прихода — работает и офлайн
- осадные груза не несут; одна точка — одно войско; точка исчезла до прихода — возврат без добычи
- истощённая/исчезнувшая точка заменяется новой того же ресурса в другом месте (детерминированно)
- события GatherStarted, GatherFinished; порядок событий по времени с учётом сбора и исчезновения точек
- сохранение в секции world (points); старые сохранения без точек читаются

Зачисление груза — Экономика через IEconomy (как трофеи боя), код Валдемара не менялся.
Таблица WorldResourceConfig (Assets/Resources/WorldResourceConfig.asset).

Карта мира: точки — ромбы цвета ресурса с запасом и сроком; окно отправки с запасом, добычей,
грузом и прогнозом «унесут N за T»; окно «ТОЧКИ НЕТ»; подпись отряда «сбор», время с часами.
Город: окно «ВОЙСКО ВЕРНУЛОСЬ» пишет «Сбор … ресурсы собраны».

Открыто (не задано регламентом): число точек на карте (сейчас по 2 каждого ресурса), выбор размера,
предел добычи на точку. Позже: нападение на занятую точку, «Связь Волхвов», переполнение склада.

Тесты: появление и расстановка, сбор и груз, истощение и новая точка, осадные без груза, исчезновение
до прихода и во время сбора, одна точка — одно войско, сохранение посреди сбора. Все 54 теста проходят вне Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 16:28:50 +01:00

8.3 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=…, jobs=…, lastTick=… и др.)
production Добыча (простые строки: slots=…, eff=…, pending=…)

Формат файла

Версия 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 (лимиты склада пересчитает App/CitySync по зданиям);
  • Добыча — мест нет (построек нет);
  • Поселение — Ратуша 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.
  • Номер версии файла поднимать при каждом несовместимом изменении и дописывать перенос старой версии здесь.

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

Дата Кто Что
31.10.2026 Claude Секция world: ресурсные точки (points: запасы, сроки, кто собирает). Старые сохранения без точек читаются — точки появятся при первом расчёте мира.
27.10.2026 Claude Секция world: добавлен список разбитых лагерей camps.
27.10.2026 Claude Новая секция production; в секции economy — список capacities (лимиты склада).
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. Запись до загрузки запрещена. Сохранение города вынесено в модуль Поселения, походов — в модуль Мира.