# Архитектура Документ описывает, как устроен проект: какие есть слои, кто кому имеет право звонить и как данные ходят по системе. Структура папок — прямое отражение этих слоёв, см. [README](../README.md#структура-репозитория). ## Слои и правила зависимостей Стрелка «→» читается как «может знать о». Всё, что не указано, — запрещено. ``` main ──→ autoload ──→ core │ ├───→ ui ────────→ core, data ├───→ world ─────→ core, data, entities ├───→ systems ───→ core, data ├───→ entities ──→ core, data └───→ debug ─────→ (всё, только для разработки) ``` | Слой | Зачем | Чего в нём быть не должно | | --- | --- | --- | | `core` | Утилиты, базовые типы, математика сетки | Ссылок на конкретные сцены и геймплей | | `data` | Описания контента: схемы (`Resource`) и их экземпляры (`.tres`) | Логики поведения — только данные | | `systems` | Симуляция мира: время, климат, погода, экономика | Прямого доступа к нодам сцены | | `world` | Визуализация и взаимодействие с убежищем | Правил симуляции — они в `systems` | | `entities` | Жители, предметы; их состояние и поведение | Знания о конкретном UI | | `ui` | Экраны, HUD, контролы | Изменения состояния мира напрямую | | `debug` | Дев-консоль, оверлеи, читы | Кода, от которого зависит релизная логика | Ключевое правило: **`ui` и `world` не меняют состояние мира сами** — они шлют намерение (сигнал/вызов системы), а изменение делает `systems`. Обратно `systems` не дёргает ноды: он сообщает об изменении сигналом. ## Данные и рендер разделены Симуляция не должна зависеть от того, нарисовано ли что-то на экране. - **Данные** (`systems`, `data`) — чистая логика: считаются от `delta`, полностью сериализуемы, тестируются без дерева сцены. - **Рендер** (`world`, `ui`) — читает данные и отображает, подписавшись на сигналы. Практический критерий: любой класс из `systems` должен работать в юнит-тесте, где никакой сцены нет. ## Обмен сообщениями Три способа, в порядке предпочтения: 1. **Сигнал вверх, вызов вниз.** Родитель знает о детях и вызывает их методы; ребёнок о родителе не знает и только испускает сигналы. 2. **Ссылка на систему**, полученную из автозагрузки — когда нужен ответ здесь и сейчас (запрос состояния, валидация постройки). 3. **Глобальная шина (`EventBus` в `autoload`)** — только для событий, которые слушают несколько несвязанных слоёв (например, «время перескочило», «погода сменилась»). Не превращать её в свалку: каждый сигнал документируем. ## Контент — это ресурсы, а не код Новая комната, предмет или тип породы добавляются как `.tres` в `data/tables/` по схеме из `data/resources/`, без правки кода. Если для добавления контента приходится менять `.gd` — схема неполная, чинить надо схему. ## Автозагрузки Автозагрузка — дорогая вещь: она живёт всю сессию и её видно отовсюду. Заводим только для того, что действительно глобально и одно на игру. Каждая новая автозагрузка регистрируется через *Project Settings → Autoload* и упоминается здесь. Сейчас в проекте: `_mcp_game_helper` — служебная, часть плагина `godot_ai`, к игровой логике отношения не имеет. ## Решения Существенные развилки (выбор подхода к сохранению, к сетке, к тайм-степу) фиксируем как ADR в [`adr/`](adr/) — короткая заметка «контекст → решение → последствия». Это дешевле, чем через полгода восстанавливать мотивацию по коду.