# Vanguard ReMaster — состояние сессии **Дата:** 2026-10-24 **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 реестр соединений. - Тесты: **151** правил + **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 не предлагается; атака по-прежнему запрещена. Смена — драг карты из руки на VC. Списки всех возможных смен в панелях убраны; действия доступны из меню выбранной карты в руке. - Призыв: клик по карте в руке открывает меню действий (Призвать / Сменить / Активировать способность / Подробнее), drag в RC/VC выполняет призыв/смену. Если у RC доступен единственный круг перемещения, перемещение выполняется сразу, без выбора цели. Призыв разрешён и в занятый RC; прежний юнит уходит в Дроп. Правило действует для обычного призыва, призыва из души/колоды и выбора круга способностями. - Аудит всех 66 карт со способностями и правила реализации: `docs/ability-implementation.md`. Conroe получил AUTO-call при ride-over. - Способности: кнопка «Активировать способность» одна на карту; при нескольких вариантах открывается overlay выбора способности. Карта для сброса выбирается **кликом по карте в руке**, а не пунктом меню. Perfect Guard также просит выбрать карту сброса в руке. Клик по карте в руке с активируемой способностью открывает меню действий; пункт активации показывается, если фаза и условия позволяют способность. - Триггеры: Draw после выбора цели силы сразу тянет карту; Heal выбирает карту только в своей зоне урона и только при выполнении условий, иначе дополнительный эффект не активируется. - Оплата способности: выбранные карты цены подсвечиваются в руке, а для Counter Blast — доступные и выбранные карты в зоне урона. Подтверждение оплаты — кнопка «Подтвердить оплату» в панели «Действия»; правый клик отменяет выбор. - Защита: в панели «Действия» одна кнопка — «Не защищаться» без выбора и «Защищаться» с выбранными картами. Защитник из руки должен быть не выше ранга своего авангарда. Карты защиты и перехвата выбираются кликом/драгом по объектам; допустимые подсвечиваются, выбранные — зелёным. Щит выбранных карт сразу учитывается в счётчике; после подтверждения карты уходят в зону защиты, шаг защиты завершается. Дубли карт в Guardian устранены. - Локальный 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`-лок больше не накапливается на каждом снапшоте. - 3D UX (P0/P1): `CardMoveAnimator` переносит карты по дуге с stagger/`InputLock`; diff идёт по `InstanceId`, пул сохраняет карту при смене зоны. `AnimationConfig` расширен (`moveDuration`, `importantMoveDuration`, `moveDelayBetweenCards`, `arcHeight`, camera/grow/dash). Trigger Zone: своя +90°, противника −90° относительно базы; `DropZoneFaceDown` в конфиге. `CameraDirector` + `TriggerCheckSequence`: zoom → hold → return, цепочка, точный Restore; `EnsureCamera` не перезаписывает камеру во время цепочки. `ArrowDirector`: красная attack и синяя boost-стрелка, grow/arc/dash (UV-tile), якоря у края карт. Multi-target Counter Blast: выбранные карты урона уходят массивом `DamageIndexes`, сервер снимает именно их; счётчик выбора показывается в панели «Действия». Детали — `docs/3d-ux-backlog.md`. - Опциональные 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`. - Tejas может атаковать задний ряд противника своей колонки как с RC, так и с VC (центральный задний ряд). - Drag в бою: задний ряд → свой передний круг/Авангард объявляет поддержку, после чего атаковать можно только поддерживаемой картой; передний круг → карта противника объявляет атаку. Авангард поддерживается центральным задним кругом. Barcgal имеет ACT `[Rest]` — поиск Llew/Flogal в колоде с выбором круга призыва; найденные карты показываются оверлеем с плитками карт и выбираются кликом по карте. Morgana после принятия способности просит сбросить карту: доступные карты в руке подсвечиваются, выбор — кликом по карте. - Реальные арты: `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-валидация декбилдера. Камера боя в покое фиксирована, но `CameraDirector` временно ведёт trigger-последовательность. Не перенесены отдельные retire/ghost анимации, `AttackResolutionQueue`, multi-target Soul Blast, world-space Power/Shield. ## Запуск Сервер (на `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 ``` Клиентские проверки: **42/42** EditMode (сборка всех экранов, импорт арта, перевод статических/динамических строк, live-переключение языка, рендер 3D-доски с уроном и отдыхающей картой, геометрия поля, правила перемещения, рука в поле зрения камеры, обмен колоды/дропа, триггер-зона, CardListView/Detail, зоны и рука противника, InputLock, контекстное меню, стрелка атаки, prefab-оверлеи, раскладка на 1920×1080, авто-завершение муллигана без кнопки после обмена, одна кнопка защиты в панели действий, отсутствие дублей карт в Guardian), `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. 3D UX: P0 (движение, ориентации, камера/триггер) и базовый P1 (стрелки, multi-target Counter Blast) готовы. Осталось: `AttackResolutionQueue`, multi-target Soul Blast/прочие стоимости, world-space Power/Shield, world-space dash shader; полировка позиций на конкретном мониторе. 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`.