VanguardReMaster/docs/SESSION-STATE.md

336 lines
25 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.

# Vanguard ReMaster — состояние сессии
**Дата:** 2026-10-23
**HEAD:** см. `git log -1`
**Коротко:** сервер готов, клиент — рабочий каркас с 3D-сценами.
## Правила работы
- Ответы короткие, без повторов и длинных вступлений — экономия токенов.
- Любое сомнение/вопрос — диалог: 2–4 варианта с рекомендацией, выбор за
пользователем (или его свободный ответ). Не угадывать.
- Полный свод правил — `AGENTS.md`.
## Сервер
- .NET 10 / ASP.NET Core, EF Core, PostgreSQL, Redis, опциональный Orleans.
- Реализовано: auth/JWT, онбординг, коллекция, колоды, магазин, экономика,
матчмейкинг, WebSocket-матч, история, реплеи.
- Orleans включается `Orleans:Enabled`; в compose включён. Один silo,
in-process реестр соединений.
- Тесты: **144** правил + **45** серверных, CI зелёный.
- Стенд: `http://192.168.31.158:18080`, `/health` → ok.
- Диагностика Ride в `MatchGrain`: входящие интенты, результат, события,
снапшоты и `rideReady` по руке/рангам; логи через `docker compose logs`.
- Документация: `docs/server-api.md`, `docs/protocol.md`,
`docs/game-rules.md`, `docs/HANDOFF.md`.
## Клиент
- **Unity 6000.6.6f1**, URP; проект в `client/`.
- Пакеты: URP, Input System, Addressables, Localization, Newtonsoft.Json,
VContainer (OpenUPM).
- Визуальное направление: **3D**, отдельные сцены-экраны:
`Login`, `Lobby`, `DeckBuilder`, `Battle`.
`DeckBuilder` совмещает коллекцию и колоды; `Boot` — стартовая служебная
сцена; `VanguardApp` персистентный.
- Переходы — `SceneFlow`; очередь/онбординг — оверлеи **Lobby**.
- 3D-окружение сейчас из примитивов (`SceneEnvironment`): камера, свет,
пол, тематические кубы. UI — code-generated uGUI, пока gray-box.
- Интерфейс рассчитан на reference **1920×1080** (`CanvasScaler`,
`matchWidthOrHeight = 0.5`); standalone принудительно открывается в
1920×1080 fullscreen, `defaultIsNativeResolution` выключен.
- Login: тёмный неон + 3D-карточный стол, форма по центру на
полупрозрачной панели.
- Сервисы: `ApiClient`, `AuthService`, `MetaService`, `TokenStore`,
`PlayerState`, `GameConnection`.
- Работает: логин/регистрация/refresh, онбординг, коллекция с разбором,
декбилдер в духе HS (список колод справа, карточная сетка коллекции,
фильтры в оверлее, сортировка клан→ранг→имя, редактор с вертикальным
списком карт колоды и статистикой по рангам/общему числу),
магазин (бустер/триал-дека), история матчей и реплей, очередь,
WebSocket-матч (snapshot, интенты, маллиган, сдача, `GameFinished`),
таймер, результат.
- Декбилдер: `DeckBuilderView`; каталог метаданных — `GET /api/cards`
(grade, trigger, clan, rarity, printing, power/shield/type, текст
способности), клиент объединяет с коллекцией.
Изображения карт — реальные арты из `Resources/CardArt` (124/124), с
процедурным fallback по цвету клана.
- ПКМ по карте — оверлей с картой, способностями, разбором в пыль и
крафтом; SP/TD не разбираются и не крафтятся.
- Локализация RU/EN: `Loc` + `LocalizedText`; переключатель в Login и
Lobby (кнопка `EN`/`RU`), выбор сохраняется в `PlayerPrefs`. Русские
строки остаются ключами, переводятся и статические, и динамические
подписи; имена/тексты карт берутся из `nameRu/nameEn` и `textRu/textEn`.
- Тренировка с ботом: кнопка «С ботом» в редакторе колоды; сервер
создаёт casual-матч против случайного бота (`POST /api/game/practice`),
без истории, MMR и наград.
- Боевой экран: поле, рука и стопки — **3D** (`GameBoard3D`), HUD/кнопки
остаются uGUI. Карты — тонкие 3D-объекты с артом, рубашкой, торцом и
коллайдером. Rest (атака/поддержка) — поворот по часовой стрелке вокруг Y,
урон лежит на боку против часовой; закрытость — переворот вокруг X.
Рубашка — стандартная VF Vanguard (`Resources/CardArt/vanguard_back.png`),
общая для 2D и 3D. Рука закреплена в поле зрения камеры снизу по центру
и всегда смотрит на игрока, а не лежит на столе; уменьшена, чтобы не
закрывать задний ряд RC. Камера фиксирована по центру поля под небольшим
углом к горизонту и не двигается игроком: `(0, 4.2, -8)`, цель
`(0, 0, 0)`, FOV 46; наклон только по X, без бокового смещения. Драг-н-дроп
на плоскость стола с подсветкой целей и плавным снапом.
Все карты на столе и в руке увеличены на 25% (`cardScale = 1.25`).
- Поле: у каждого игрока два ряда `R V R` / `R R R` (V + 5 RC), у
противника зеркально; между полями общий круг защиты; колода, дроп,
триггер-зона и урон — 3D-зоны. Локальный игрок всегда снизу, даже если
он за вторым местом. Карты в кругах V/R принудительно показываются
лицом вверх; урон — один вертикальный ряд, карта входит открытой.
Над колодой — зона проверки триггера. Под картами V/R — динамические
`P/C`.
- Смена: в фазе Ride доступны карты того же ранга и на 1 выше. На первом
ходу переход в Battle не предлагается; атака по-прежнему запрещена.
Кнопки «Сменить: карта» есть и в панели действий, и в панели «Фазы».
- Способности: кнопка «Активировать способность» одна на карту; при
нескольких вариантах открывается overlay выбора способности. Карта для
сброса выбирается **кликом по карте в руке**, а не пунктом меню.
Perfect Guard также просит выбрать карту сброса в руке.
- В фазе защиты доступны «Защититься» (если есть допустимые карты) и
«Не защищаться»; карта защиты и карта сброса выбираются в руке.
- Локальный standalone работает в фоне (`runInBackground`), чтобы heartbeat
WebSocket не останавливался при потере фокуса.
- При потере соединения весь бой блокируется полноэкранным overlay
«Соединение потеряно»; автоматический reconnect идёт с задержками
0/2/10/30 с, после успеха overlay скрывается и поле показывается снова.
Кнопка внутри overlay позволяет выйти в меню.
- Правую панель действий можно временно скрыть кнопкой «Скрыть панель»
в верхней строке; поле остаётся видимым, вернуть — «Показать панель».
При скрытии панель фаз и блоки противника сдвигаются вправо, а рука
центрируется по горизонтали; при показе возвращается влево.
- Кнопка муллигана находится в панели «Фазы» и динамическая: без выбора —
«Закончить муллиган», с выбором — «Заменить X карт».
- Trigger-зона у противника расположена над его колодой по направлению
к центру стола (зеркально своей), а не за дальним краем.
- Статистика карт — отдельное UI-наложение: своя панель снизу слева,
противника — сверху справа. Блоки `Рука/Колода/Дроп/Душа/Урон/Защита/Триггер`
кликабельны и открывают общий горизонтальный `CardListView`; из списка
открывается `CardDetailOverlay`. Для колоды и руки противника показываются
только закрытые карты. Душа — юниты под VC: отдельной стопки нет,
ПКМ по VC открывает список. Дроп по умолчанию пуст; сверху показывает
последнюю карту, ЛКМ — список всего дропа. Колода и дроп поменяны
местами (колода ближе к игроку). Справа от круга защиты — панель фаз:
конец муллигана (авто после обмена), скип смены, конец главной/боевой;
боевая завершается сама, если нет атак и активаций. Рука противника —
веер закрытых карт у дальнего края стола, только рубашки.
- Зона урона: карты лежат открытыми и на боку; после Counter Blast
выбранная карта переворачивается рубашкой. Heal выбирает карту урона;
Counter Blast — открытую карту до активации способности.
- Маллиган: один раз на игрока, оба игрока; выбранные карты уходят в низ
колоды, добираются новые, затем shuffle. Клик по руке выбирает карты;
кнопка динамическая: без выбора — «Закончить муллиган», с выбором —
«Заменить X карт».
- Анимации: event-фидбек (атака, guard, drive, урон, retire, heal) поверх
стола; ввод заблокирован до завершения через `InputLockService`, очередь
событий + кнопка «Пропустить анимации». Длительности и скорости карт —
`AnimationConfig` (`Resources/AnimationConfig`). Guard/drive/intercept
показывают имя карты и держатся 1.5–2 с. 3D-карты плавно снапятся,
поворачиваются в Rest и переворачиваются; подсветка целей и точки броска
обновляются на каждом снимке. Зависшие причины `InputLockService`
снимаются, когда reconnect/overlay/ability/card-menu/feedback уже
неактивны; `board`-лок больше не накапливается на каждом снапшоте.
- Опциональные AUTO-способности (Barcgal после рейда Marron) открывают
модальный оверлей «Способность» с «Активировать»/«Пропустить»; в боковой
панели этих кнопок нет. После подтверждения призыва сервер предлагает
`AskEmptyRearGuardChoice`, клиент подсвечивает свободные RC и принимает
выбор кликом по кругу — первого круга по умолчанию нет и отдельных
кнопок выбора тоже. Сама панель пока оставлена.
- Общий верхний `ActionPrompt` показывает, что сейчас требуется: муллиган,
смена, защита, бой, выбор карты/круга/цели, триггер, порядок триггеров,
опциональная способность. Он не перехватывает клики и скрыт в ход
противника.
- Правило: выбор карты/круга/зоны/цели делается кликом/драгом по объекту
на поле, не кнопками; кнопки — только глобальные действия/подтверждения.
Зафиксировано в `AGENTS.md` и `docs/client-visual-direction.md`.
- Бой: динамическая плашка `POWER X vs SHIELD Y` (Power атакующего против
Power защищающегося + GuardShield), пересчитывается на каждом снимке, в
том числе после Guard. От атакующего к цели идёт затухающая 3D-стрелка,
которая следует за картами. ЛКМ по своей карте V/R открывает контекстное
меню с действиями из `LegalIntents` (атака/boost, перемещение, способность,
подробнее); карты противника и зоны открывают детали/списки. ПКМ по VC —
душа. Guardian-карты повёрнуты на 90° и уложены с перекрытием ~30%,
новые сверху; Trigger-зона зеркальна у противника. 3D-подписи зон скрыты,
включаются флагом `showZoneLabels`.
- Drag в бою: задний ряд → свой передний круг/Авангард объявляет поддержку,
после чего атаковать можно только поддерживаемой картой; передний круг →
карта противника объявляет атаку. Авангард поддерживается центральным
задним кругом. Barcgal имеет ACT `[Rest]` — поиск Llew/Flogal в колоде с
выбором круга призыва; найденные карты показываются оверлеем с плитками
карт и выбираются кликом по карте.
- Реальные арты: `imageKey` из `/api/cards` + `CardImageService` ищет
`Resources/CardArt/{imageKey}`. Скачаны все 124 арта. Импорт:
`tools/import_card_art.py`.
- Взаимодействие в бою: клик по картам/зонам, подсветка целей,
группировка действий (карты → цели, глобальные кнопки отдельно),
выбор силы/эффекта триггера, журнал последних событий. Позванные
rear-guard'ы входят в стоячем положении; rest — только после атаки/буста.
Атака проходит при силе атакующего **>=** силы защищающегося.
В первый ход атака запрещена; первый игрок определяется сидом.
- Отдельная сцена `Collection` и `CollectionView` удалены; коллекция
открывается из Lobby кнопкой «Коллекция» (сцена `DeckBuilder`).
- Не готово: 3D-модели карт/стола (пока процедурные примитивы и арты),
звук, настройки (язык уже есть), DOTween, drag&drop и live-валидация
декбилдера. Камера боя фиксирована; анимации retire/ghost для
3D-карт ещё не перенесены.
## Запуск
Сервер (на `ssh home`):
```bash
cd ~/VanguardReMaster
docker compose up -d --build
curl http://127.0.0.1:18080/health
```
Клиент:
1. Unity Hub → `client`, редактор **6000.6.6f1**.
2. Открыть `Assets/Scenes/Boot.unity`, Play.
3. Стенд по умолчанию — `http://192.168.31.158:18080`.
Standalone Windows:
- В редакторе: `Vanguard → Build Windows Standalone`.
- Из CLI (пример для копии проекта):
```powershell
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
-batchmode -nographics -projectPath client `
-executeMethod Vanguard.Editor.StandaloneBuild.BuildWindowsCli -quit
```
- Результат: `client/Builds/Windows/VanguardReMaster.exe` (папка в
`.gitignore`). Это обычное приложение, не Play Mode; сервер должен быть
доступен по адресу из `AppConfig`.
## Проверки клиента
```powershell
# EditMode
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
-batchmode -nographics -projectPath client `
-runTests -testPlatform EditMode -testResults client\TestResults.xml
# Boot → Login + 3D environment
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
-batchmode -nographics -projectPath client `
-executeMethod Vanguard.Editor.SceneSmoke.Run
# 3D playmat sandbox
& 'C:\Program Files\Unity\Hub\Editor\6000.6.6f1\Editor\Unity.exe' `
-batchmode -nographics -projectPath client `
-executeMethod Vanguard.Editor.SceneSmoke.RunPlaymat
```
Клиентские проверки: **35/35** EditMode (сборка всех экранов, импорт арта,
перевод статических/динамических строк, live-переключение языка, рендер
3D-доски с уроном и отдыхающей картой, геометрия поля, правила
перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона,
CardListView/Detail, зоны и рука противника, InputLock, контекстное меню,
стрелка атаки, prefab-оверлеи, раскладка на 1920×1080, авто-завершение
муллигана без кнопки после обмена), `SCENE_SMOKE
success=True`, `PLAYMAT_SMOKE success=True cards=25 hand=5/5 fieldVisible=True`.
`SceneSmoke` заменяет PlayMode-тест загрузки сцен: Single-загрузка сцены
ломает стандартный PlayMode test runner. `SceneBuilder` пересобирает сцены:
```powershell
& '...\Unity.exe' -batchmode -nographics -projectPath client `
-executeMethod Vanguard.Editor.SceneBuilder.BuildAll
```
## Ключевые файлы клиента
```
client/Assets/Vanguard/Runtime/App/
VanguardApp.cs composition root, персистентный
SceneFlow.cs переходы Login/Lobby/DeckBuilder/Battle
SceneEnvironment.cs 3D-фон сцен
SceneControllerBase.cs
LoginSceneController.cs
LobbySceneController.cs
DeckBuilderSceneController.cs
BattleSceneController.cs
client/Assets/Vanguard/Runtime/UI/
LoginView.cs MetaView.cs OnboardingView.cs
DeckBuilderView.cs QueueView.cs BattleView.cs
UiKit.cs Localization.cs
client/Assets/Vanguard/Runtime/UI/Overlays/
OverlayNavigationService.cs стек список → детали
CardListView.cs общий горизонтальный список
CardDetailOverlay.cs крупная карта и текст
CardListModels.cs зоны и скрытые карты
ZoneBlockStripView.cs кликабельные блоки зон
CardActionMenuView.cs контекстное меню карты
OverlayPrefabs.cs загрузка prefab-оверлеев
client/Assets/Vanguard/Editor/
OverlayPrefabBuilder.cs сборка Resources/Overlays/*.prefab
StandaloneBuild.cs Windows standalone build
client/Assets/Vanguard/Runtime/Battle/
AnimationConfig.cs длительности/скорости анимаций
InputLockService.cs блокировка ввода по причинам
GameConnection.cs
client/Assets/Vanguard/Runtime/Board3D/
Config/PlaymatLayoutConfig.cs ScriptableObject-раскладка
Data/BoardTypes.cs зоны, круги, CardState3D, refs
Logic/PlaymatLayout.cs геометрия, рука, поиск цели броска
Logic/BoardPlacementRules.cs Ride/Call/Move/Guard
View/GameBoard3D.cs стол, круги, пул карт, drag&drop
View/Card3D.cs карта: лицо/рубашка/торец, Rest, флип
View/AttackArrowView.cs стрелка атаки с наконечником
PlaymatSandbox.cs демо без сервера
client/Assets/Vanguard/Resources/AnimationConfig.asset настройки анимаций
client/Assets/Vanguard/Resources/Overlays/*.prefab prefab-оверлеи
client/Assets/Vanguard/Resources/CardArt/vanguard_back.png рубашка VF
client/Assets/Vanguard/Scenes/GameBoard3D.unity песочница поля
client/Assets/Vanguard/Runtime/Api/ApiClient.cs + ApiContracts.cs
client/Assets/Vanguard/Editor/SceneBuilder.cs + SceneSmoke.cs
client/Assets/Vanguard/Scenes/*.unity
client/Assets/Plugins/Vanguard.Shared + MessagePack
```
## Решения
- 3D-визуал, отдельные сцены; подробно — `docs/client-visual-direction.md`.
- `Boot` не показывается; `VanguardApp`/сервисы не пересоздаются.
- Очередь — оверлей Lobby; DeckBuilder «В бой» возвращает в Lobby с
выбранной колодой в `SceneFlow.PendingQueueDeck`.
- Токены в `PlayerPrefs` — dev; для релиза защищённое хранилище.
- HTTP разрешён только для dev (`insecureHttpOption: 2`); для релиза HTTPS.
- `GameConnection` использует `System.Net.WebSockets.ClientWebSocket`
(Windows/десктоп first); WebGL потребует другого транспорта.
- Сервер авторитарный; клиент отправляет только интенты, скрытые данные
не покидают сервер.
## Следующие шаги
1. UX-план 3D-поля: Phase 2–4 закрыты, overlay-экраны вынесены в prefab
(`Resources/Overlays`), раскладка проверена на 1920×1080 и масштабируется
CanvasScaler'ом. Осталось при желании отполировать позиции на конкретном
мониторе.
2. Декбилдер: drag&drop, счётчики лимитов, live-валидация, пресеты.
3. 3D-наполнение: модели карт/стола, prefab-экраны сцен, анимации retire/ghost.
4. Звук и настройки, DOTween.
5. Лаунчер WPF.
Тренировка с ботом и боевой UI с артами/анимациями/локализацией уже есть.
## Подводные камни
- Не запускать `dotnet`/Docker на рабочем ПК; сервер проверяется на `ssh home`.
- В Unity нельзя открыть два экземпляра одного проекта: для batch-проверок
делать копию проекта (без `Library`) или закрывать редактор.
- Сцены ссылаются на скрипты по GUID; при копировании сцен копировать и
`.meta` контроллеров.
- `Vanguard.Shared.dll` — netstandard2.1 + MessagePack 3.1.12; при изменении
протокола пересобрать DLL и заменить в `client/Assets/Plugins`.
- `UiKit.CreateCanvas` по умолчанию **не** персистентный: Canvas принадлежит
сцене; EventSystem остаётся персистентным.
- Сцена `Boot` должна быть первой в Build Settings; сейчас там
`Boot`, `Login`, `Lobby`, `DeckBuilder`, `Battle`.