Files
MVP1/Docs/Modules/Save.md
T
AlexanderandClaude Opus 5.5 15b06b8f42 Модули Чата и Круга, разворот чата на весь экран, кнопка «Почта» в Safe Area
Модуль Чата (Bogatyri.Chat, без Unity):
- чат вынесен из Social в отдельный модуль; контракт IChat в ядре,
  событие ChatMessageReceivedEvent, LocalPlayer (id и имя игрока)
- панель чата работает только через контракт и события
- разворот чата на весь экран: кнопка «Развернуть/Свернуть» или Esc

Модуль Круга (Bogatyri.Circle, без Unity):
- основать Круг, вступить, выйти; роли главы и участника; 30 мест
- уход главы передаёт главенство, последний участник распускает Круг
- секция сохранения "circle", участвует в сбросе сохранений
- окно «Круг» (кнопка внизу карты мира), демо-Круги до появления сервера
- канал «Круг» в чате — только для участников Круга

Прочее:
- кнопка «Почта» привязана к правому краю нижней панели
  (в безопасной зоне она уезжала за экран)
- тесты Чата и Круга; документы Chat.md, Circle.md, обновлены README, Core, Save

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:07:45 +02:00

105 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сохранения
Игровое состояние: запись и загрузка `save.json`. Модуль не знает, что хранят другие модули: каждый модуль сам отдаёт свою секцию.
- **Сборка:** `Bogatyri.Save`.
- **Папка:** `Assets/Scripts/Modules/Save`.
- **Зависит от:** ядра.
## Контракт `ISaveSystem`
| Член | Что делает |
| --- | --- |
| `HasSave` | Есть ли файл сохранения. |
| `SaveNow()` | Сохранить сейчас. |
| `DeleteSave()` | Только стереть файл (состояние модулей в памяти не меняется). |
| `ResetAll()` | **Сброс сохранений**: все модули возвращаются к новой игре, файл сразу перезаписывается. |
Для слоя приложения остаются `SaveManager.Instance.SaveGame()`, `LoadGame()`, `HasSaveFile()`, `DeleteSave()`.
## Как модуль подключает свои данные
```csharp
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) |
## Формат файла
Версия 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 уровня, постройки убраны, участки свободны;
- **Мир** — все походы отменены;
- **Круг** — игрок ни в каком Круге, его Круги распущены.
Новый модуль с данными обязан реализовать `ResetState()`, иначе он не скомпилируется: метод входит в контракт.
## События
**Публикует:**
- `GameLoadedEvent` — после загрузки;
- `GameSavedEvent` — после записи;
- `GameResetEvent` — после сброса сохранений.
**Слушает:** ничего.
## Файлы
| Файл | Что это |
| --- | --- |
| `SaveManager.cs` | Запись и чтение секций, автосохранение, перенос версии 1. |
| `GameBootstrap.cs` | Загружает сохранение при старте сцены города. |
| `Assets/Editor/SaveResetMenu.cs` (редактор) | Меню Tools → Сбросить сохранения / Открыть папку сохранений. |
## Решения и план
- **Этап 0:** одно сохранение. `GameProgress` (`progress.json`: герой, задания, почта, войска) пока пишет свой файл. Его данные переводятся в секции по мере выноса в модули: первыми — войска (модуль Армии).
- Номер версии файла поднимать при каждом несовместимом изменении и дописывать перенос старой версии здесь.
## Журнал изменений
| Дата | Кто | Что |
| --- | --- | --- |
| 19.10.2026 | Claude | Новая секция `circle` (модуль Круга). |
| 19.10.2026 | Claude | Сброс сохранений: `ISaveSystem.ResetAll()`, `ResetState()` у модулей, `GameResetEvent`, меню редактора. Кнопка в Настройках теперь сбрасывает и походы, и память Поселения. |
| 19.10.2026 | Claude | `SaveManager` переписан на секции модулей (`ISaveParticipant`), формат v2 с переносом v1. Запись до загрузки запрещена. Сохранение города вынесено в модуль Поселения, походов — в модуль Мира. |