VanguardReMaster/IMPLEMENTATION_CHECKLIST.md

282 lines
19 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.

# Базовая версия — чеклист реализации
Практический план: что писать, в каком порядке и когда считать готовым.
Дизайн-решения и обоснования — в `DEVELOPMENT_CHECKLIST.md`. Данные карт — в `content/cards-mvp.md`.
---
## 0. Границы базовой версии
**Входит:**
- Платформа: Windows. Unity + WPF-лаунчер.
- Формат: `Classic`, один сет — BT01 + TD01 + TD02 (94 карты).
- Аккаунт, коллекция, полный декбилдер, магазин бустеров и триал-дек.
- 2 очереди: Classic Ranked и Classic Casual. Матч 1×1, BO1.
- Полный игровой цикл: матч → результат → Gold/XP → бустер → карта в коллекцию.
- Базовый туториал + выдача триал-деки и 5 токенов.
- Локализация RU + EN.
- Лаунчер с проверкой версии и докачкой.
**Не входит:** турниры, команды, территории, чат, друзья, баттлпасс, квесты, Draft, косметика, мобилка, реплеи в клиенте (только серверная запись).
### Стек (зафиксирован)
| Слой | Технология |
|---|---|
| Сервер | **.NET 10 LTS**, ASP.NET Core, Orleans, EF Core, PostgreSQL 16, Redis 7 |
| Протокол матча | TCP + MessagePack, кадры с префиксом длины |
| Мета-API | HTTP/JSON, JWT |
| Клиент | Unity 6 LTS, URP, Addressables, Input System, Unity Localization, DOTween |
| Лаунчер | WPF, **.NET 10 LTS**, CommunityToolkit.Mvvm |
| Контейнеры | Docker Compose, nginx |
### Оценка (один разработчик, полный день)
| Этап | Дни |
|---|---|
| 1. Репозиторий и каркас | 2–3 |
| 2. Контент-пайплайн | 4–6 |
| 3. Игровое ядро | 20–30 |
| 4. Скрипты 94 карт | 15–25 |
| 5. Сеть и матч | 8–12 |
| 6. Мета-API | 10–14 |
| 7. Клиент: каркас и меню | 15–20 |
| 8. Клиент: боевая сцена | 20–30 |
| 9. Туториал | 5–7 |
| 10. Лаунчер | 5–7 |
| 11. QA и сборка | 7–10 |
| **Итого** | **~110–165** |
---
## 1. Репозиторий и каркас `[2–3 дня]`
- [x] `git init`, ветка `master`.
- [x] `.gitignore`: Unity (`Library/`, `Temp/`, `Logs/`, `UserSettings/`, `Builds/`), .NET (`bin/`, `obj/`), WPF (`publish/`), секреты (`.env`, `appsettings.Production.json`).
- [x] Отдельно игнорировать только Unity-генерируемые `*.csproj`/`*.sln` в `/client`, чтобы не убить `server/*.sln`.
- [x] `.gitattributes`: `* text=auto eol=lf`, `*.unity`, `*.prefab`, `*.asset` → `merge=unityyamlmerge`, `*.png`/`*.wav` → `binary`.
- [x] Структура (на 20.10.2026 — `server`, `content`, `tools`; `client` и `launcher` появятся со своими блоками):
```
/server
Vanguard.slnx
/src/Vanguard.Rules чистое ядро правил, без Orleans и БД
/src/Vanguard.Content загрузчик и валидатор контента
/src/Vanguard.Shared контракты, DTO, MessagePack
/src/Vanguard.Cli headless-раннер матчей
/tests/Vanguard.Rules.Tests
/content/sets/BT01.yaml
/content/sets/TD01.yaml
/content/sets/TD02.yaml
/tools/import_cards.py
```
- [x] `Directory.Build.props`: `net10.0`, `Nullable=enable`, `LangVersion=latest`.
- [ ] `docker-compose.yml`: postgres, redis (AOF), meta-api, game-silo, nginx.
- [ ] `docker compose up` поднимает БД и пустой API; healthcheck отвечает.
- [ ] CI: сборка solution + `dotnet test` на push.
**Готово, когда:** `docker compose up` + `dotnet run` дают живой `/health`.
---
## 2. Контент-пайплайн `[4–6 дней]`
- [x] Схема YAML: `printingId`, `nameId`, `cardType`, `grade`, `power`, `shield`, `critical`, `triggerType`, `clan`, `rarity`, `isSentinel`, `isRestraint`, `name_en/ru`, `text_en/ru`, `imageKey`.
- [x] Импорт с официального сайта → три YAML-файла (BT01, TD01, TD02). 94 карты, 124 принта.
- [x] Валидатор:
- [x] `sum(deck) = 50`, `≤4` по `nameId`, `≤4` Sentinel, `≤4` Heal.
- [x] Инвариант щита: grade 0 → 5000 **только** у Draw, иначе 10000.
- [x] Уникальность `printingId`, наличие `nameId`.
- [x] Ссылка SP-принта на существующий базовый номер.
- [x] Загрузчик: YAML → in-memory каталог, используется и сервером, и тестами.
- [x] Ключевые слова и шаблоны: `content/keywords.yaml`, `content/translations/ru.yaml`, команды `translations build|check`.
- [ ] Сид в PostgreSQL: `cards`, `printings`, `sets`, `card_legality` (пустая).
- [ ] Экспорт каталога для клиента (JSON + список Addressables-ключей).
**Готово:** `dotnet run --project server/src/Vanguard.Cli -- validate` → `94 карты, 124 принта, 0 ошибок`.
---
## 3. Игровое ядро `[20–30 дней]` — критический путь
Пишется **как чистая библиотека**: без Orleans, без БД, без сети. Вход — состояние + интент, выход — новое состояние + события.
- [x] `GameState`: игроки, зоны, фазы, счётчики, `rngState`.
- [x] Зоны: Vanguard, Rear-Guard (3 колонки × 2 ряда), Guardian, Soul, Damage, Drop, Trigger, Deck, Hand.
- [x] Юнит: `instanceId`, `printingId`, состояние Stand/Rest.
- [x] Damage: список карт с `faceUp`, скрыт от обоих игроков.
- [x] Фазы: Mulligan → Stand → Draw → Ride → Main → Battle → End.
- [x] Старт: выбор grade 0 → выставление → маллиган.
- [x] Действия: Ride, Call, Attack, Guard, Drive, Damage, Stand/Rest, Retire, Draw.
- [ ] Move, Intercept, Boost, Discard, Shuffle как отдельные интенты.
- [ ] `driveCheckCount` как модифицируемое свойство (сейчас константа 2).
- [x] Результат боя: `Hit` / `Guarded` как событие.
- [ ] Событийная шина и три обработчика: Continuous / Activated / Triggered.
- [ ] Check Timing: сбор → сортировка → разрешение по одному → повтор.
- [ ] Стоимости: CB, SB, discard, rest self, retire self, put to soul, return to deck.
- [ ] Цели: авто по фильтру и выбор игроком, «до N» / «ровно N».
- [ ] Слои модификаторов силы/крита с длительностью.
- [x] Валидация интентов: `Rejected(reason)` без изменения состояния.
- [ ] Список легальных интентов на каждый момент (для UI и античита).
- [~] Детерминированный RNG: один поток на партию, состояние в `GameState`.
- [~] Журнал событий + seed; сериализуемый реплей ещё не сделан.
- [ ] Защита от бесконечных циклов и дедлоков.
**Сделано:** каркас движка (`Engine/`), 8 тестов на старт, райд, призыв, атаку, защиту, урон и детерминизм. Всего 30 тестов.
**Готово, когда:** два бота случайными легальными интентами доигрывают 1000 партий без падений, инварианты (сумма карт, счётчики ≥ 0) держатся, реплей воспроизводится бит-в-бит.
---
## 4. Карты `[15–25 дней]`
- [ ] Хелперы: `Draw`, `Retire`, `SearchCall`, `SearchHand`, `SearchRide`, `Stand`, `SoulCharge`, `SoulBlast`, `CounterBlast`, `FlipDamage`, `ToSoul`, `ToDeck`, `Discard`, `LookTop`, `ModifyPower`, `ModifyCrit`, `GainKeyword`.
- [ ] Шаблон карты: 1 файл = 1 `nameId`, комментарий с официальным текстом и ссылкой.
- [ ] Порядок: TD01 → TD02 → BT01 (сначала ванильные, потом со способностями).
- [ ] По каждой карте: скрипт + тест «дано → сыграл → ожидаю».
- [ ] RU/EN тексты для всех 94.
- [ ] Сила/щит для 14 карт, которых нет в BT01.
- [ ] Дашборд покрытия: `scripted / tested / total`.
**Готово, когда:** 94/94 заскриптованы, 94/94 покрыты тестом, приёмка пройдена по чеклисту карты.
---
## 5. Сеть и матч `[8–12 дней]`
- [ ] Спецификация протокола в `docs/protocol.md`: кадры, handshake, версия, ping/pong, reconnect.
- [ ] `Vanguard.Shared`: DTO интентов и событий, MessagePack-резолвер.
- [ ] `IGameTicketService`: одноразовый тикет на подключение (TTL 60 с).
- [ ] TCP-сервер: accept, handshake, auth по тикету, привязка к grain.
- [ ] `IMatchGrain`: 1 матч = 1 grain, последовательная обработка.
- [ ] Проекция состояния под клиента: своя рука, свой trigger, открытые зоны; **ничего** о колоде, руке противника и закрытом уроне.
- [ ] `eventSeq` + `resync` по запросу.
- [ ] Реконнект: 0 / 2 / 10 / 30 с, затем экран «не удалось».
- [ ] Политика отсутствия: 5 минут → авто-поражение.
- [ ] Таймер хода: 90 с + банк 5 мин.
- [ ] Снапшот матча в PostgreSQL + восстановление grain после рестарта.
- [ ] Idempotency по `intentId`.
**Готово, когда:** два клиента играют полный матч по сети; kill процесса клиента на любом шаге восстанавливается.
---
## 6. Мета-API `[10–14 дней]`
- [ ] Модель `User`, BCrypt, JWT (access 15 мин + refresh 30 дней, ротация).
- [ ] Эндпоинты: `register`, `login`, `refresh`, `logout`, `me`.
- [ ] Коллекция: `GET /collection` (сгруппировано по принтам), счётчики без верхней границы.
- [ ] Колоды: CRUD, `validate`, лимит 30 на формат, шаринг по коду.
- [ ] Магазин: `GET /store`, `POST /buy/booster`, `POST /buy/trialdeck`, `POST /redeem/token`.
- [ ] Генератор бустера: слот `4 × C` + `1 × R+` (R 70 / RR 22 / RRR 7 / SP 1).
- [ ] Duplicate protection по `printingId`, замена внутри редкости, переброс редкости при её насыщении.
- [ ] Экономика: журнал транзакций, `idempotencyKey`, баланс вычисляемый.
- [ ] Пыль: разбор C 5 / R 10 / RR 25 / RRR 100, крафт ×4, SP не крафтится.
- [ ] Онбординг: выбор триал-деки + 5 токенов, флаг «выбор сделан».
- [ ] Матчмейкинг: 2 очереди, скрытый MMR, расширяющееся окно.
- [ ] Результат матча: начисление Gold 30/15/20 и XP 150/75/100, запись в историю.
- [ ] Rate limiting на все мутирующие эндпоинты.
**Готово, когда:** новый игрок через API проходит путь регистрация → триал-дека → токены → бустеры → колода → очередь.
---
## 7. Клиент: каркас и меню `[15–20 дней]`
- [ ] Unity 6 LTS, URP, Addressables, Input System, Localization, DOTween.
- [ ] Сцены: `Boot`, `Meta`, `Battle`.
- [ ] Composition root + DI (VContainer), без синглтон-свалок.
- [ ] `ApiClient` (HTTP/JSON), `MetaState`, обработка офлайна и таймаутов.
- [ ] `GameConnection` (TCP + MessagePack), очередь событий, `ClientGameState`.
- [ ] Экраны: логин/регистрация, главное меню, профиль (минимальный), магазин, коллекция, декбилдер, очередь, настройки.
- [ ] Декбилдер: фильтры (клан, грейд, редкость, тип, арт), счётчики, валидация в реальном времени.
- [ ] Коллекция: арты раздельно, «сколько в колодах», разбор в пыль с подтверждением.
- [ ] Магазин: бустер (анимация открытия), триал-деки, обмен токенов.
- [ ] Локализация RU/EN, переключение на лету.
- [ ] Настройки: язык, звук, FPS, мьют.
**Готово, когда:** все мета-экраны работают против реального сервера, язык переключается без перезапуска.
---
## 8. Клиент: боевая сцена `[20–30 дней]`
- [ ] Поле: Vanguard, 2 колонки × 2 ряда, Guardian, рука, Damage, Soul, Drop, Trigger.
- [ ] Старт: выбор grade 0, маллиган.
- [ ] Ввод: клик/тап → контекстное меню → подсветка валидных целей.
- [ ] Отображение силы/крита с модификаторами и подсветкой баффов.
- [ ] Очередь анимаций строго по событиям сервера: ride, call, attack, drive, damage, retire, boost, guard.
- [ ] Скип/ускорение анимаций.
- [ ] Экран противника: таймлайн и текстовый лог боя.
- [ ] Таймер хода, индикатор реконнекта, кнопка сдачи.
- [ ] Экран результата: победа/поражение, Gold/XP, кнопка «ещё матч».
- [ ] Догон состояния после реконнекта (resync + переигрывание очереди).
**Готово, когда:** полный матч играется мышью без консоли и без рассинхрона с сервером.
---
## 9. Туториал `[5–7 дней]`
- [ ] `TutorialStep` как ScriptableObject: текст, подсветка, ожидаемое действие.
- [ ] Сценарий: Ride → Call → Boost → Attack → Drive Check → Damage Check → победа.
- [ ] Работает поверх реального движка (локальный матч), не фейковая сцена.
- [ ] Кнопка «Пропустить».
- [ ] По завершении: выбор триал-деки + 5 токенов + флаг онбординга.
**Готово, когда:** новый аккаунт с нуля доходит до первой своей колоды без подсказок извне.
---
## 10. Лаунчер `[5–7 дней]`
- [ ] WPF, MVVM, тёмная тема, окно 1000×640.
- [ ] Логин через тот же API, сохранение refresh-токена в DPAPI.
- [ ] `version.json`: `clientVersion`, `minVersion`, список файлов `{path, hash, size, url}`.
- [ ] Проверка хешей локальных файлов, докачка только изменённого.
- [ ] Прогресс, скорость, пауза, возобновление.
- [ ] Кнопка «Играть» запускает клиент с game-тикетом.
- [ ] Обработка «сервер недоступен», «нет места», «файл повреждён → перекачать».
- [ ] Самообновление лаунчера.
- [ ] Установщик (Inno Setup), установка без прав администратора.
**Готово, когда:** чистая машина → установка → логин → докачка → запуск игры.
---
## 11. Сборка и QA `[7–10 дней]`
- [ ] Скрипт сборки: сервер (docker), клиент (Unity batchmode), лаунчер (dotnet publish), манифест, загрузка на CDN.
- [ ] Тестовый стенд: БД с бесконечной валютой, аккаунты QA.
- [ ] Прогон «золотых матчей»: 50 реплеев воспроизводятся после каждого изменения ядра.
- [ ] E2E: регистрация → туториал → бустеры → колода → матч → награда.
- [ ] Проверка скрытой информации: дамп трафика не содержит руки и колоды противника, закрытого урона и seed.
- [ ] Проверка реконнекта на 20 разных шагах.
- [ ] Профилирование клиента: 60 FPS на средней машине.
- [ ] Инструкция запуска для нового разработчика (README).
---
## 12. Финальный коммит
- [ ] `.gitignore` актуален, в индексе нет `Library/`, `bin/`, `obj/`, `.env`, билдов.
- [ ] Нет секретов и ключей в истории (`git log -p | Select-String "password|secret|key"`).
- [ ] `git add -A` и один коммит:
```
git commit -m "Base version: server, client, launcher"
```
- [ ] Тег: `git tag v0.1.0-base`.
- [ ] Дальше — обычная история, по одному смыслу на коммит.
---
## Гейты (не двигаться дальше, пока не выполнено)
| Гейт | Критерий |
|---|---|
| **G1. Ядро** | 1000 случайных партий без падений, реплей бит-в-бит |
| **G2. Контент** | 94/94 карт заскриптованы и протестированы |
| **G3. Сеть** | Полный матч по сети, реконнект на любом шаге |
| **G4. Мета** | Регистрация → колода → ранкед матч → награда |
| **G5. Клиент** | Полный цикл мышью, без консоли |
| **G6. Доставка** | Чистая машина → установка → игра |