19 KiB
Базовая версия — чеклист реализации
Практический план: что писать, в каком порядке и когда считать готовым.
Дизайн-решения и обоснования — в 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 дня]
git init, веткаmaster..gitignore: Unity (Library/,Temp/,Logs/,UserSettings/,Builds/), .NET (bin/,obj/), WPF (publish/), секреты (.env,appsettings.Production.json).- Отдельно игнорировать только Unity-генерируемые
*.csproj/*.slnв/client, чтобы не убитьserver/*.sln. .gitattributes:* text=auto eol=lf,*.unity,*.prefab,*.asset→merge=unityyamlmerge,*.png/*.wav→binary.- Структура (на 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 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 дней]
- Схема YAML:
printingId,nameId,cardType,grade,power,shield,critical,triggerType,clan,rarity,isSentinel,isRestraint,name_en/ru,text_en/ru,imageKey. - Импорт с официального сайта → три YAML-файла (BT01, TD01, TD02). 94 карты, 124 принта.
- Валидатор:
sum(deck) = 50,≤4поnameId,≤4Sentinel,≤4Heal.- Инвариант щита: grade 0 → 5000 только у Draw, иначе 10000.
- Уникальность
printingId, наличиеnameId. - Ссылка SP-принта на существующий базовый номер.
- Загрузчик: YAML → in-memory каталог, используется и сервером, и тестами.
- Ключевые слова и шаблоны:
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, без БД, без сети. Вход — состояние + интент, выход — новое состояние + события.
GameState: игроки, зоны, фазы, счётчики,rngState.- Зоны: Vanguard, Rear-Guard (3 колонки × 2 ряда), Guardian, Soul, Damage, Drop, Trigger, Deck, Hand.
- Юнит:
instanceId,printingId, состояние Stand/Rest. - Damage: список карт с
faceUp, скрыт от обоих игроков. - Фазы: Mulligan → Stand → Draw → Ride → Main → Battle → End.
- Старт: выбор grade 0 → выставление → маллиган.
- Действия: Ride, Call, Attack, Guard, Drive, Damage, Stand/Rest, Retire, Draw.
- Move, Intercept, Boost, Discard, Shuffle как отдельные интенты.
driveCheckCountкак модифицируемое свойство (сейчас константа 2).- Результат боя:
Hit/Guardedкак событие. - Событийная шина и три обработчика: Continuous / Activated / Triggered.
- Check Timing: сбор → сортировка → разрешение по одному → повтор.
- Стоимости: CB, SB, discard, rest self, retire self, put to soul, return to deck.
- Цели: авто по фильтру и выбор игроком, «до N» / «ровно N».
- Слои модификаторов силы/крита с длительностью.
- Валидация интентов:
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. Доставка | Чистая машина → установка → игра |