234 lines
16 KiB
Markdown
234 lines
16 KiB
Markdown
# Vanguard ReMaster — состояние сессии
|
||
|
||
**Дата:** 2026-10-22
|
||
|
||
**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 реестр соединений.
|
||
- Тесты: **138** правил + **45** серверных, CI зелёный.
|
||
- Стенд: `http://192.168.31.158:18080`, `/health` → ok.
|
||
- Документация: `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.
|
||
- 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. Камера фиксирована над полем под небольшим
|
||
углом и не двигается игроком: `(1.4, 5.8, -8)`, цель `(1.4, 0, 0)`,
|
||
FOV 46. Драг-н-дроп на плоскость стола с подсветкой целей и плавным
|
||
снапом.
|
||
- Поле: у каждого игрока два ряда `R V R` / `R R R` (V + 5 RC), у
|
||
противника зеркально; между полями общий круг защиты; колода, дроп,
|
||
триггер-зона и урон — 3D-зоны. Локальный игрок всегда снизу, даже если
|
||
он за вторым местом. Карты в кругах V/R принудительно показываются
|
||
лицом вверх; урон — один вертикальный ряд, карта входит открытой.
|
||
Над колодой — зона проверки триггера. Под картами V/R — динамические
|
||
`P/C`.
|
||
- Статистика карт — отдельное UI-наложение: своя панель снизу слева,
|
||
противника — сверху справа. Душа — юниты под VC: отдельной стопки нет,
|
||
ПКМ по VC открывает список. Дроп по умолчанию пуст; сверху показывает
|
||
последнюю карту, ЛКМ — список всего дропа. Колода и дроп поменяны
|
||
местами (колода ближе к игроку). Справа от круга защиты — панель фаз:
|
||
конец муллигана (авто после обмена), скип смены, конец главной/боевой;
|
||
боевая завершается сама, если нет атак и активаций.
|
||
- Зона урона: карты лежат открытыми и на боку; после Counter Blast
|
||
выбранная карта переворачивается рубашкой. Heal выбирает карту урона;
|
||
Counter Blast — открытую карту до активации способности.
|
||
- Маллиган: один раз на игрока, оба игрока; выбранные карты уходят в низ
|
||
колоды, добираются новые, затем shuffle. Клик по руке выбирает карты.
|
||
- Анимации: event-фидбек (атака, guard, drive, урон, retire, heal) поверх
|
||
стола, не блокирует ввод; очередь событий + кнопка «Пропустить анимации».
|
||
Guard/drive/intercept показывают имя карты и держатся 1.5–2 с, чтобы
|
||
успеть прочитать защиту бота. 3D-карты плавно снапятся, поворачиваются
|
||
в Rest и переворачиваются; подсветка целей и точки броска обновляются
|
||
на каждом снимке.
|
||
- Реальные арты: `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`.
|
||
|
||
## Проверки клиента
|
||
|
||
```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
|
||
```
|
||
|
||
Клиентские проверки: **20/20** EditMode (сборка всех экранов, импорт арта,
|
||
перевод статических/динамических строк, live-переключение языка, рендер
|
||
3D-доски с уроном и отдыхающей картой, геометрия поля, правила
|
||
перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона),
|
||
`SCENE_SMOKE success=True`,
|
||
`PLAYMAT_SMOKE success=True cards=22 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/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, флип
|
||
PlaymatSandbox.cs демо без сервера
|
||
client/Assets/Vanguard/Resources/CardArt/vanguard_back.png рубашка VF
|
||
client/Assets/Vanguard/Scenes/GameBoard3D.unity песочница поля
|
||
client/Assets/Vanguard/Runtime/Battle/GameConnection.cs
|
||
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. Декбилдер: drag&drop, счётчики лимитов, live-валидация, пресеты.
|
||
2. 3D-наполнение: модели карт/стола, prefab-экраны, анимации retire/ghost.
|
||
3. Звук и настройки, DOTween.
|
||
4. Лаунчер 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`.
|