Модульная система: игровое ядро + 6 модулей, документы Docs/Modules

- Ядро (Bogatyri.Core): контракты модулей, EventBus, GameServices, SaveRegistry
- Модули: Экономика, Поселение, Армия, Глобальный мир, Боевая система, Сохранения
  (каждый — отдельный asmdef, видит только ядро)
- App/GameModules: регистрация модулей и связь с GameProgress/Казармами
- Сохранения v2 по секциям модулей, перенос старого save.json и походов из progress.json
- Сброс сохранений: ISaveSystem.ResetAll, ResetState у модулей, меню Tools
- EditMode-тесты модулей, документы по каждому модулю с журналом изменений

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-10-19 18:39:28 +02:00
co-authored by Claude Opus 5.5
parent bcb870f62e
commit 964cb23d9d
99 changed files with 2296 additions and 631 deletions
@@ -0,0 +1,14 @@
{
"name": "Bogatyri.Core.Unity",
"rootNamespace": "",
"references": ["Bogatyri.Core"],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 189d07a7182d0984599ea459f965a9ea
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,16 @@
using UnityEngine;
// Unity-часть ядра: подключает чистое ядро (без Unity) к движку.
public static class CoreUnityBootstrap
{
// Самый ранний момент запуска игры -- раньше любых Awake.
// Чистим статику: в редакторе с выключенной перезагрузкой домена она переживает прошлый Play.
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void ResetCore()
{
GameServices.Clear();
EventBus.Clear();
SaveRegistry.Clear();
EventBus.OnHandlerError = Debug.LogException;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e1017811ac1606e48b62e813e60ee061
@@ -0,0 +1,24 @@
using UnityEngine;
using UnityEngine.EventSystems;
// Проверка "палец/мышь сейчас над UI?".
// Нужна, чтобы клик по кнопке панели НЕ проходил насквозь в мир:
// не собирал ресурсы со здания под панелью, не улучшал Ратушу, не двигал камеру.
public static class UIBlocker
{
public static bool IsPointerOverUI()
{
if (EventSystem.current == null) return false;
// мышь (редактор/ПК) и новый Input System
if (EventSystem.current.IsPointerOverGameObject()) return true;
// тач на телефоне (старый input module требует id пальца)
for (int i = 0; i < Input.touchCount; i++)
{
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(i).fingerId))
return true;
}
return false;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 54a1703640ad8894cb8f75fb798c6685