Армия (п. 2.1): - ReturnFromMarch / ReturnUnits возвращают bool и зачисляют воинов только по известному походу и только один раз (раньше неизвестный поход добавлял выживших пехотой, ReturnUnits — без ограничения) - вернуться может не больше, чем ушло - TakeForMarch отклоняет повторный номер похода (раньше перезапись теряла воинов первого) - загрузка сохранения и перенос старых данных пропускают дубликаты походов Мир (п. 2.2): - TryStartMarch проверяет TakeForMarch; при отказе поход откатывается (WorldSimulation.CancelMarch) - если Армия не знает возвращающийся поход — ни воинов, ни добычи, предупреждение в консоли Тесты (п. 2.1, 2.2, 2.4): - неизвестный поход, повторное возвращение, повторный номер, откат похода - крайние случаи боя: 1×1, 1×10, 10×1, 0×0, пустая сторона, бонусы −100% / −500% / +100000%, бой числом Формула потерь не менялась. Найдено и записано в Battle.md как открытый вопрос: одиночный проигравший не гибнет (потери округляются вниз) — правило округления решает команда. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.2 KiB
8.2 KiB
Игровое ядро
Общие данные, игровые правила взаимодействия и связь модулей. Ядро не содержит игровой логики — только «язык», на котором модули говорят друг с другом.
- Сборки:
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<T>, Get<T>, TryGet<T>, Has<T>, Unregister<T>. |
Core/WorkJob.cs |
Профессии рабочих WorkJob и WorkJobs (какой ресурс добывает профессия, русское название). Числа enum не менять: они в сохранениях. |
Core/GameClock.cs |
Часы игры: UnixNow = реальное время + сдвиг. Advance(секунд) — перемотка для отладки, публикует GameTimeAdvancedEvent. Сдвиг не сохраняется. Модули берут время только отсюда. |
Core/EventBus.cs |
Шина событий: Subscribe<T>, Unsubscribe<T>, Publish<T>. Ошибка одного подписчика не мешает остальным (уходит в 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) |
Жители, рабочие по профессиям, воины, предел жилья, расход еды и прирост в час, голод; Tick — досчитать до момента. |
IArmy |
Армия (ArmyService) |
Войска по типам, в городе и в походах; обучение, потери; забрать в поход, вернуть выживших. |
IWorld |
Мир (MarchManager) |
Сколько походов в пути; начать поход. |
IBattleSystem |
Бой (BattleSystem) |
Посчитать исход боя по BattleRequest: состав сторон по типам, стены, бонусы. |
IChat |
Чат (ChatService) |
История каналов, можно ли писать в канал, отправка сообщения от локального игрока. |
ICircle |
Круг (CircleService) |
Круг игрока, список Кругов; основать, вступить, выйти. |
ISaveSystem |
Сохранения (SaveManager) |
Есть ли сохранение; сохранить сейчас; стереть; сбросить всё (ResetAll). |
ISaveParticipant |
Любой модуль с данными | Секция сохранения: ключ, Capture(), Restore(json), ResetState() — новая игра. |
Порядок запуска
SubsystemRegistration—CoreUnityBootstrapочищает ядро.AfterAssembliesLoaded—App/GameModulesиSettlementModuleрегистрируют сервисы и подписки.BeforeSceneLoad— создаётсяMarchManager(Мир).Awakeобъектов сцены —ResourceManager,SaveManagerрегистрируются сами.AfterSceneLoad— перенос старых походов изprogress.json.Start—GameBootstrapзагружает сохранение или, если файла нет, публикуетNewGameStartedEvent.- Раз в 2 секунды —
App/PopulationTickerдосчитывает Население.
Решения и план
- Решение команды от 19.10.2026: единый источник истины для населения, армии и ресурсов. Новые контракты для этапов 1, 2 и 5 — население, гарнизон, голод, лимиты хранения — добавляются сюда, когда начинается соответствующий этап.
Журнал изменений
| Дата | Кто | Что |
|---|---|---|
| 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. |