# 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 реестр соединений. - Тесты: **142** правил + **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) открывают модальный оверлей «Способность» с «Активировать»/«Пропустить»; в боковой панели этих кнопок нет. Сама панель пока оставлена. - Бой: динамическая плашка `POWER X vs SHIELD Y` (Power атакующего против Power защищающегося + GuardShield), пересчитывается на каждом снимке, в том числе после Guard. От атакующего к цели идёт затухающая 3D-стрелка, которая следует за картами. ЛКМ по своей карте V/R открывает контекстное меню с действиями из `LegalIntents` (атака/boost, перемещение, способность, подробнее); карты противника и зоны открывают детали/списки. ПКМ по VC — душа. Guardian-карты повёрнуты на 90° и уложены с перекрытием ~30%, новые сверху; Trigger-зона зеркальна у противника. 3D-подписи зон скрыты, включаются флагом `showZoneLabels`. - Реальные арты: `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 ``` Клиентские проверки: **32/32** 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`.