Скаффолдинг игрового плагина (create-vimp-game)
Движок не импортирует игровой код по пути: игра — отдельный npm-пакет, который поставляет dist/manifest.json и два бандла. Написать такой пакет с нуля — значит воспроизвести сборочный конвейер, крейт на Rust, схему снапшота и примерно три десятка «тихих» инвариантов ещё до первого пикселя; обычный результат — плагин, который собирается, но так и не появляется в лобби.
create-vimp-game пишет этот пакет за вас, причём сразу играбельный:
npm create vimp-game my-gameГенератор публикуется как самостоятельный npm-пакет create-vimp-game; у него нет рантайм-зависимостей, поэтому npm create не тянет дерево пакетов перед первым вопросом.
Команда
npm create vimp-game <directory> [-- <опции>]Всё после -- уходит скаффолдеру. Без --yes и при живом терминале он задаёт шесть вопросов (каталог, id игры, название, имя пакета, автор, репозиторий); с --yes, под пайпом и в CI — молча берёт значения по умолчанию.
| Опция | Значение |
|---|---|
--id <id> | id игры, kebab-case — сегмент URL /games/<id>/, ключ каталога и HostPlugin.id (по умолчанию: имя каталога, нормализованное) |
--title <title> | человекочитаемое название (по умолчанию: id с заглавных) |
--package <name> | имя npm-пакета (по умолчанию: @vimp-games/<id>) |
--repository <url> | репозиторий проекта, полный URL или user/repo — пишется и в repository, и в homepage; движок ставит в форме входа игры ссылку на homepage (иначе repository), а правило A7 предупреждает, когда поля нет (по умолчанию не пишется вовсе) |
--author <name> | author в package.json и в LICENSE |
--yes, -y | принять все значения по умолчанию, ничего не спрашивать |
--force | разрешить непустой целевой каталог |
--no-git | не делать git init (первый коммит всегда ваш) |
--engine-path <p> | только для разработки: зависимость от локального чекаута движка |
--core-path <p> | только для разработки: [patch.crates-io] для vimp-engine-core |
--help, --version | справка / собственная версия скаффолдера |
cargo и wasm-pack проверяются после генерации. Их отсутствие — это предупреждение, а не отказ: проект создаётся в любом случае, иначе ошибка всплыла бы на npm run core:build, когда чинить ещё нечего.
Версии в шаблоне не захардкожены. Пины vimp-engine и vimp-engine-core читаются из src/versions.generated.json, который пишет хук prepack при публикации. Устаревший пин — тихая поломка, всплывающая только на сборке ядра, поэтому в шаблоне нет ни одного версионного литерала, которому есть чему устареть.
Что получается
Минимальная, но полноценная игра — не копия tanks и не скелет из TODO:
- две играющие команды и зрители, один класс актора, одно hitscan-оружие, одна карта, боты;
- вся графика процедурная (PixiJS
Graphicsплюс bakers): бинарных картинок в пакете нет вообще. Звук — две плейсхолдер-парыwebm+mp3, конвейерassets/audio-raw/→npm run audio:processподключён, но необязателен (ему нужен ffmpeg); - полная сборочная инфраструктура из plugin-api.md: два режима Vite (
client,host), пять скриптов сборки, Cargo-воркспейс с крейтом<id>-core, Vitest с проектамиunitиintegration, ESLint; - Rust-ядро, где математика движения лежит в одном
motion.rs, общем для серверного шага и клиентского предиктора, с parity-тестом, стерегущим эту общность; - dev-харнес (
index.html+dev/main.js), запускающий standalone-матч с ботами — см. standalone.md; CLAUDE.md, где записаны границы потоков, константы контракта и команды проверки — для того, кто (или что) будет дописывать геймплей.
Раскладка и контракты по файлам: plugin-api.md и packaging.md; там же описано, какую документацию обязан поставлять готовый плагин (Документация, которую обязан поставлять плагин).
Цикл проверки
В сгенерированном проекте, в таком порядке:
npm install
npm run core:build # cargo + wasm-pack → core/pkg-web, core/pkg-node
npm run check:contract # vimp-contract: статическая проверка контракта
npm run core:test # cargo test --workspace (включая parity-тест)
npm test && npx eslint .
npm run build # dist/: оба бандла, карты, звуки, manifest.json
npm run sim # headless-матч на настоящем ядре, смена хоста каждые 0.5 с
npm run dev # тот же матч в браузере, против ботовnpm run core:build — не опция и не «потом»: dev/main.js импортирует wasm из core/pkg-web/, поэтому пока ядро не собрано хотя бы раз, npm run dev падает на старте, не сумев разрешить этот импорт.
check:contract — шаг, который окупается. Это vimp-contract из пакета движка: 34 правила по package.json, vite.config.js, core/Cargo.toml, dist/manifest.json и по обеим половинам плагина, импортированным как модули; правило без входных данных отвечает skip, поэтому инструмент применим с первого коммита. Он ловит ровно тот класс ошибок, который иначе доезжает до браузера чёрным холстом: неверное имя параметра авторизации, ключ снапшота без записи в gameSets, парт, забытый в entitiesOnCanvas. Подробности: debugging.md.