Справочник игрового SDK
@caputchin/game-sdk это контракт, против которого пишет автор игры: хелпер register, push-only Bridge, пер-раундовый GameContext и типы TypeScript для блоков пресетов манифеста. Он публикуется отдельно от обращённого к пользователю виджета, так что игры никогда транзитивно не встраивают рантайм виджета. Собственные игры используют тот же публичный API; приватного контракта нет.
Для руководимого построения смотри Построй игру для маркетплейса. Для манифеста, который объявляет пресеты, выводимые этим SDK, смотри Манифест caputchin.json.
register(factory)
Единственная точка входа регистрации. Передай свою игровую фабрику; ты не передаёшь манифест (сервер читает caputchin.json во время индексации и шлёт разрешённые пресеты вниз как контекст фабрики). Регистрация дважды логирует предупреждение в консоль, и побеждает последняя запись; платформенного принуждения нет.
register(factory: GameFactory): voidИгровая фабрика
type GameFactory = (
container: HTMLElement,
bridge: Bridge,
ctx?: GameContext,
) => (() => void) | void| Параметр | Значение |
|---|---|
container | Элемент внутри iframe игры в песочнице. Рендери сюда. Стиль естественно ограничен, iframe это свой собственный документ. |
bridge | Push-only канал к хосту (смотри Мост). Игра испускает вверх; она не подписывается. Вызванная фабрика и есть сигнал старта. |
ctx | Пер-раундовый контекст (сид плюс разрешённые пресеты). Опционален в типе, потому что виджет может запустить игру вне проверенной сессии. |
| return | Опциональная функция очистки, которую виджет вызывает, если размонтирует твою игру. |
Мост
Мост push-only: игра отчитывается о событиях хосту и никогда не слушает. Его члены:
| Член | Форма | Эффект |
|---|---|---|
pass | pass(result: { trace: string }): void | Сигналит, что раунд пройден, вручая хосту непрозрачную trace. Сервер перезапускает run игры под выданным сидом, чтобы вычислить авторитетный вердикт, так что игра не отчитывается о счёте здесь. Первый вызов отпускает удерживаемую проверку и блокирует токен; поздние вызовы игнорируются. |
error | error(err: { code: string; message?: string }): void | Сама игра сбоила (загрузка ассета, внутреннее исключение). Всплывает событием error пользователю. Отлично от проигрыша игрока, о котором сигналят, не вызывая ничего. |
setSize | setSize(width: number, height: number): void | Явно изменить размер iframe под содержимое. Вызови после первой отрисовки; виджет также авто-измеряет первого ребёнка игры, так что большинству игр это никогда не нужно. |
layout | readonly layout: 'inline' | 'modal' | 'fullscreen' | null | Разрешённое представление, под которым работает игра, или null, когда неизвестно. |
Намеренно нет complete, нет слушателя start, нет метода unmount (возвращай функцию очистки вместо этого) и нет сигнала сбоя помимо молчания.
Контекст
interface GameContext {
seed: Seed | null
locale: ResolvedLocale | null
skin: ResolvedSkin | null
config: ResolvedConfig | null
}| Поле | Значение |
|---|---|
seed | Пер-раундовый сид реплея (Seed из контракта реплея). Засевай всю случайность игры из него. null, когда игра работает вне проверенной сессии. |
locale | Разрешённый объект языка: _lang (BCP-47), _direction плюс твои уплощённые текстовые ключи. null, если твой манифест не поставляет блока locales. |
skin | Разрешённый скин: _theme плюс твои уплощённые ключи цвета/ассета, URL ассетов уже абсолютные. _theme всегда конкретный режим, под который разрешён скин, light или dark (никогда any), так что тема-агностичный пресет сообщает реальный режим посетителя. null, если нет блока skins. |
config | Разрешённая конфигурация: твои уплощённые типизированные скаляры. null, если нет блока configurations. |
Каждый null, когда соответствующий блок манифеста отсутствует, так что всегда предоставляй встроенный откат.
Типы пресетов
SDK экспортирует типы TypeScript для авторствования caputchin.json (и сплит-файлов .caputchin/) с проверкой типов. Они зеркалят блоки манифеста:
| Тип | Описывает |
|---|---|
GameManifest | Весь caputchin.json. Источник истины автора + индексатора; никогда не читается в браузере. |
LocalePreset / ResolvedLocale | Объявленный пресет локали / разрешённый объект, который получает игра. |
SkinPreset / ResolvedSkin / SkinSchemaEntry / SkinValueType | Пресеты скина, разрешённый скин и типовая схема на каждый ключ. |
ConfigPreset / ResolvedConfig / ConfigSchemaEntry / ConfigValueType | Пресеты конфигурации, разрешённый config и типовая схема на каждый ключ. |
LocalesFile / SkinsFile / ConfigurationsFile | Объект верхнего уровня каждого сплит-файла .caputchin/<axis>.json. |
MarketplaceMetadata / PreferredPresentation | Блок marketplace и подсказка следа preferred. |
Авторствуй сплит-файл с импортом satisfies, чтобы компилятор его проверял:
import type { LocalesFile } from "@caputchin/game-sdk";
export default { schema: { /* ... */ }, presets: { /* ... */ } } satisfies LocalesFile;Что намеренно отсутствует
- Никакой
sessionIdили платформенные идентификаторы не доходят до игры. - Нет хуков жизненного цикла
start/pause/resume; вызов фабрики это старт. - Нет
maxScoreили платформенного диапазона счёта; счёт вердикта это то, что возвращает твойrun.
Контракт намеренно крошечный, чтобы оставаться стабильным сквозь годы роста каталога.
См. также
- Построй игру для маркетплейса: руководство, которое использует эту поверхность.
- Контракт реплея:
Seed, трасса и вердикт, на которые ссылаются мост и контекст. - Манифест caputchin.json: объявление пресетов, которые разрешает контекст.