# Игровое ядро Общие данные, игровые правила взаимодействия и связь модулей. Ядро не содержит игровой логики — только «язык», на котором модули говорят друг с другом. - **Сборки:** - `Bogatyri.Core` — чистый C#, без Unity (его можно взять на сервер); - `Bogatyri.Core.Unity` — тонкая прослойка к движку. - **Папки:** `Assets/Scripts/Modules/Core`, `Assets/Scripts/Modules/Core.Unity`. - **Зависимости:** нет. От ядра зависят все модули. ## Что внутри | Файл | Что это | | --- | --- | | `Core/ResourceType.cs` | Перечисление ресурсов `ResourceType` и структура `ResourceAmount` (тип + количество). Числа enum не менять: они в сохранениях. | | `Core/LocalPlayer.cs` | Id и имя локального игрока (пока без аккаунтов). | | `Core/GameServices.cs` | Реестр модулей: `Register`, `Get`, `TryGet`, `Has`, `Unregister`. | | `Core/WorkJob.cs` | Профессии рабочих `WorkJob` и `WorkJobs` (какой ресурс добывает профессия, русское название). Числа enum не менять: они в сохранениях. | | `Core/GameClock.cs` | Часы игры: `UnixNow` = реальное время + сдвиг. `Advance(секунд)` — перемотка для отладки, публикует `GameTimeAdvancedEvent`. Сдвиг не сохраняется. Модули берут время только отсюда. | | `Core/EventBus.cs` | Шина событий: `Subscribe`, `Unsubscribe`, `Publish`. Ошибка одного подписчика не мешает остальным (уходит в `OnHandlerError`). | | `Core/Contracts/ModuleContracts.cs` | Контракты всех модулей и `SaveRegistry` — см. таблицу ниже. | | `Core/Events/GameEvents.cs` | Все события модулей. | | `Core.Unity/CoreUnityBootstrap.cs` | При старте игры очищает реестр, шину и список сохраняемых, сбрасывает перемотку `GameClock`, подключает ошибки шины к `Debug.LogException`. | | `Core.Unity/UIBlocker.cs` | «Палец над интерфейсом?» — общая проверка для кликов по миру. | ## Контракты | Контракт | Реализует | Что умеет | | --- | --- | --- | | `IEconomy` | Экономика (`ResourceManager`) | Узнать, добавить, потратить ресурс; проверить и списать цену целиком; лимит склада. | | `IProduction` | Экономика (`ProductionService`) | Места для рабочих по профессиям, эффективность, добыча в час; `Produce` — добыть за время. | | `ISettlement` | Поселение (`SettlementModule`) | Уровень Ратуши, число построек, открыт ли город. | | `ILeveledBuilding` | Здания с уровнем (`ResourceCollector`) | Уровень здания — его сохраняет Поселение. | | `IPopulation` | Население (`PopulationService`) | Жители, рабочие по профессиям, воины, предел жилья, расход еды и прирост в час, голод и его история (`WasStarvingAt`), найм воинов из жителей; `Tick` — досчитать до момента. | | `IArmy` | Армия (`ArmyService`) | Войска по типам, в городе и в походах; обучение, потери; забрать в поход, вернуть выживших. | | `IWorld` | Мир (`MarchManager`) | Сколько походов в пути; начать поход; начать поход «Разведка» (`TryStartScout`). | | `IWorldMap` | Мир (`MarchManager`) | Для Разведки: границы карты, где поселение, все армии в момент времени (`ArmyOnMap`). | | `IIntelligence` | Разведка (`IntelligenceService`) | Туман (`GetVisibility`), «Обзор», известные чужие армии (`KnownContact`), `ObserveUntil`. | | `IResourceProtection` | Город — Склады и Амбары (`App/ResourceProtection`, регистрирует `App/GameModules`) | Сколько ресурса спрятано от грабежа (`Protected`) и сколько можно унести в набеге (`Lootable`; кристаллы — только с технологией «Грабёж»: `Lootable(type, attackerHasPlunder)`). 01.11 / 04.11, ТЕСТ. | | `IHospital` | Город — здание «Госпиталь» (`HospitalBeds`, регистрирует `App/GameModules`) | Мест для лечения (`Beds`) по уровню самого прокачанного госпиталя; 0 — госпиталя нет. | | `IBattleSystem` | Бой (`BattleSystem`) | Посчитать исход боя по `BattleRequest`: состав сторон по типам, стены, бонусы. | | `IChat` | Чат (`ChatService`) | История каналов, можно ли писать в канал, отправка сообщения от локального игрока. | | `ICircle` | Круг (`CircleService`) | Круг игрока, список Кругов; основать, вступить, выйти. | | `ISaveSystem` | Сохранения (`SaveManager`) | Есть ли сохранение; сохранить сейчас; стереть; сбросить всё (`ResetAll`). | | `ISaveParticipant` | Любой модуль с данными | Секция сохранения: ключ, `Capture()`, `Restore(json)`, `ResetState()` — новая игра. | ## Порядок запуска 1. `SubsystemRegistration` — `CoreUnityBootstrap` очищает ядро. 2. `AfterAssembliesLoaded` — `App/GameModules` и `SettlementModule` регистрируют сервисы и подписки. 3. `BeforeSceneLoad` — создаётся `MarchManager` (Мир). 4. `Awake` объектов сцены — `ResourceManager`, `SaveManager` регистрируются сами. 5. `AfterSceneLoad` — перенос старых походов из `progress.json`. 6. `Start` — `GameBootstrap` загружает сохранение или, если файла нет, публикует `NewGameStartedEvent`. 7. Раз в 2 секунды — `App/PopulationTicker` досчитывает Население. ## Решения и план - **Решение команды от 19.10.2026:** единый источник истины для населения, армии и ресурсов. Новые контракты для этапов 1, 2 и 5 — население, гарнизон, голод, лимиты хранения — добавляются сюда, когда начинается соответствующий этап. ## Журнал изменений | Дата | Кто | Что | | --- | --- | --- | | 04.11.2026 | Claude | Событие `GameTimeSimulatedEvent` (расчёт дошёл до момента — для стройки в офлайне). `IResourceProtection.Lootable(type, attackerHasPlunder)` — кристаллы и технология «Грабёж». Существующие контракты не менялись. | | 01.11.2026 | Claude | Контракт `IResourceProtection` (защита ресурсов от грабежа): для будущих набегов на города — Бой и Мир берут отсюда, сколько можно унести. | | 04.11.2026 | Claude | Разведка М2: `ReconTargetKind`, `ReconTarget`, `ReconReport`; `IWorldMap.TryGetReconTarget`; `IIntelligence.ReconDurationMs/CompleteRecon/Reports/TryGetLatestReport`; `IWorld.TryStartRecon`; события `ReconStartedEvent`, `ReconCompletedEvent`. | | 04.11.2026 | Claude | Пропавшие без вести: `MissingInfo`, `IArmy.MissingTotal/Missing/MarkMissing/ProcessMissing`, `BattleOutcome.*MissingUnits`, события `MissingReturnedEvent`, `MissingWrittenOffEvent`, поля `Missing` у `TroopsChangedEvent` и `MarchReturnedEvent`. | | 01.11.2026 | Claude | Раненые (решения 31.10, п. 7): `IHospital`, `HealingInfo`; `IArmy`: `WoundedTotal`, `GetWoundedWaiting`, `Healing`, `HospitalBeds`, `ReturnUnits(…, woundedUnits, nowMs)`, `ProcessHealing`; события `SoldiersHealedEvent`, `TroopsChangedEvent.Wounded`, `MarchReturnedEvent.Wounded`. | | 01.11.2026 | Claude | `IArmy`: очередь обучения (`Training`, `CanQueueTraining`, `TryQueueTraining`, `ProcessTraining`, `FinishAllTraining`), `TrainingOrderInfo`, событие `TroopsTrainedEvent`; `GameClock.UnixNowMs` (решения 31.10, п. 8). | | 01.11.2026 | Claude | `IWorld.TryStartScout`; `IsScout` у `MarchStartedEvent` и `MarchReturnedEvent` (решения 31.10, п. 2). | | 31.10.2026 | Claude | Разведка М1: контракты `IWorldMap`, `IIntelligence` (`ArmyOnMap`, `MapVisibility`, `KnownContact`), события `WorldAdvancingEvent`, `ArmySpottedEvent`, `ArmyIdentifiedEvent`, `ArmyLostContactEvent`. | | 31.10.2026 | Claude | `IPopulation.CompleteTraining(type, n)` — передача новобранцев в Армию одним действием. | | 31.10.2026 | Claude | `IPopulation.Workforce` — все жители (ограничения «40% всех людей» больше нет), `CivilianReserve` — по уровню Ратуши. Население — самостоятельный модуль. | | 31.10.2026 | Claude | `MarchReturnedEvent.IsGather` — поход на ресурсную точку. | | 31.10.2026 | Claude | `IArmy.MarchSlots`, `IArmy.ActiveMarches` — слоты похода. | | 30.10.2026 | Claude | События похода: `TimeMs` (когда случилось по часам игры) у `MarchStartedEvent`, `MarchBattleResolvedEvent`, `MarchReturnedEvent`; `BattleId` у `MarchBattleResolvedEvent`. | | 30.10.2026 | Claude | `BattleForecast.WinChancePermille` — шанс победы (решение №11). | | 28.10.2026 | Claude | `IPopulation`: `WasStarvingAt` (история голода для боя), найм — `CivilianReserve`, `Recruitable`, `InTraining`, `TryRecruit`, `RecruitsTrained`. | | 28.10.2026 | Claude | Бой: `BattleCondition` (голод, усталость), `BattleRequest.AttackerConditions` / `DefenderConditions`, `BattleOutcome.AttackerConditionPercent` / `DefenderConditionPercent`. | | 28.10.2026 | Claude | Бой: `BattleRequest.Seed`; `BattleOutcome` — номер боя, версия правил, удача сторон, состав до боя, выжившие, погибшие и раненые по типам у обеих сторон; `IBattleSystem.Forecast`, `BattleForecast`, `BattleChance`. | | 28.10.2026 | Claude | `IArmy.ReturnFromMarch` и `IArmy.ReturnUnits` возвращают `bool`: зачисление только по известному походу и один раз. `TakeForMarch` отклоняет повторный номер похода. | | 27.10.2026 | Claude | `IArmy`: гарнизон (`GarrisonTotal`, `GetGarrison`, `AvailableForMarch`, `SetGarrison`); `TroopsChangedEvent.Garrison`. | | 27.10.2026 | Claude | `MarchReturnedEvent.TargetEmpty`: войско пришло к уже разбитому лагерю. | | 27.10.2026 | Claude | `TroopType` (типы войск), `BattleRequest` / `BattleOutcome` с составом по типам, силой сторон и бонусами; `IArmy.GetMarchUnits`, `IArmy.ReturnUnits`. | | 27.10.2026 | Claude | `WorkJob`; контракт `IProduction`; `IEconomy.GetCapacity`; `IPopulation`: `Workforce`, `FreeWorkers`, `GetWorkers`, `SetWorkers`; событие `WorkersChangedEvent`. | | 26.10.2026 | Claude | `GameClock`; контракт `IPopulation`; события `GameTimeAdvancedEvent`, `PopulationChangedEvent`, `StarvationChangedEvent`, `NewGameStartedEvent`. | | 23.10.2026 | Claude | `IArmy` расширен (типы, `AddTroops`, `LoseFraction`, `TroopsInMarches`), событие `TroopsChangedEvent`. `GameLoadedEvent` публикуется и когда файла сохранения нет. | | 19.10.2026 | Claude | Контракт `ICircle` и типы `CircleInfo`, `CircleMember`, `CircleRole`; события `CircleJoinedEvent`, `CircleLeftEvent`; `IChat.CanWrite`. | | 19.10.2026 | Claude | Контракт `IChat`, типы `ChatChannel` и `ChatMessage`, событие `ChatMessageReceivedEvent`, `LocalPlayer`. | | 19.10.2026 | Claude | Сброс сохранений: `ISaveSystem.ResetAll()`, `ISaveParticipant.ResetState()`, событие `GameResetEvent`. | | 19.10.2026 | Claude | Создано ядро: реестр, шина событий, контракты шести модулей, события, `SaveRegistry`. `ResourceType` перенесён сюда из `ResourceManager.cs`, `UIBlocker` — из `Meta/Core`. |