Caputchin
Desenvolvimento de jogo de marketplace

Referência do SDK de jogo

@caputchin/game-sdk é o contrato contra o qual um autor de jogo escreve: um ajudante register, uma Bridge de mão única, o GameContext por rodada, e os tipos TypeScript para os blocos de preset do manifesto. Ele é publicado separadamente do widget voltado ao usuário para que os jogos nunca empacotem transitivamente o runtime do widget. Os jogos próprios usam esta mesma API pública; não há contrato privado.

Para uma construção guiada, veja Construir um jogo de marketplace. Para o manifesto que declara os presets que este SDK expõe, veja O manifesto caputchin.json.

register(factory)

O único ponto de entrada de registro. Passe sua fábrica de jogo; você não passa o manifesto (o servidor lê o caputchin.json no momento da indexação e envia os presets resolvidos como o contexto da fábrica). Registrar duas vezes loga um aviso no console e a última escrita vence; não há imposição da plataforma.

register(factory: GameFactory): void

A fábrica de jogo

type GameFactory = (
  container: HTMLElement,
  bridge: Bridge,
  ctx?: GameContext,
) => (() => void) | void
ParâmetroSignificado
containerUm elemento dentro do iframe em sandbox do jogo. Renderize aqui. O estilo é naturalmente delimitado, o iframe é seu próprio documento.
bridgeO canal de mão única para o anfitrião (veja A ponte). O jogo emite para cima; ele não se inscreve. A fábrica sendo chamada é o sinal de início.
ctxO contexto por rodada (semente mais presets resolvidos). Opcional no tipo porque o widget pode rodar um jogo fora de uma sessão verificada.
returnUma função de limpeza opcional que o widget chama se desmontar seu jogo.

A ponte

A ponte é de mão única: o jogo reporta eventos ao anfitrião e nunca escuta. Seus membros:

MembroFormatoEfeito
passpass(result: { trace: string }): voidSinaliza que a rodada foi aprovada, entregando ao anfitrião o trace opaco. O servidor reexecuta o run do jogo sob a semente emitida para computar o veredito autoritativo, então o jogo não reporta uma pontuação aqui. A primeira chamada libera a verificação retida e trava o token; chamadas posteriores são ignoradas.
errorerror(err: { code: string; message?: string }): voidO próprio jogo falhou (carregamento de ativo, exceção interna). Expõe um evento error ao usuário. Distinto de um jogador perdendo, que é sinalizado não chamando nada.
setSizesetSize(width: number, height: number): voidRedimensiona explicitamente o iframe para caber o conteúdo. Chame depois do primeiro paint; o widget também auto-mede o primeiro filho do jogo, então a maioria dos jogos nunca precisa disto.
layoutreadonly layout: 'inline' | 'modal' | 'fullscreen' | nullA apresentação resolvida sob a qual o jogo roda, ou null quando desconhecida.

Não há, deliberadamente, nenhum complete, nenhum listener de start, nenhum método unmount (retorne uma função de limpeza em vez disso), e nenhum sinal de falha além do silêncio.

O contexto

interface GameContext {
  seed:   Seed          | null
  locale: ResolvedLocale | null
  skin:   ResolvedSkin   | null
  config: ResolvedConfig | null
}
CampoSignificado
seedA semente de replay por rodada (uma Seed do contrato de replay). Semeie toda a aleatoriedade do jogo dela. null quando o jogo roda fora de uma sessão verificada.
localeO objeto de idioma resolvido: _lang (BCP-47), _direction, mais suas chaves de texto achatadas. null se o seu manifesto não envia bloco locales.
skinO skin resolvido: _theme mais suas chaves de cor/ativo achatadas, com as URLs de ativo já absolutas. _theme é sempre o modo concreto para o qual o skin foi resolvido, light ou dark (nunca any), então um preset agnóstico de tema reporta o modo real do visitante. null se não houver bloco skins.
configA configuração resolvida: seus escalares tipados achatados. null se não houver bloco configurations.

Cada um é null quando o bloco de manifesto correspondente está ausente, então sempre forneça um fallback embutido.

Tipos de preset

O SDK exporta tipos TypeScript para criar o caputchin.json (e os arquivos divididos .caputchin/) com verificação de tipo. Estes espelham os blocos do manifesto:

TipoDescreve
GameManifestO caputchin.json inteiro. Fonte de verdade do autor + indexador; nunca lido no navegador.
LocalePreset / ResolvedLocaleUm preset de idioma declarado / o objeto resolvido que o jogo recebe.
SkinPreset / ResolvedSkin / SkinSchemaEntry / SkinValueTypePresets de skin, o skin resolvido, e o esquema de tipo por chave.
ConfigPreset / ResolvedConfig / ConfigSchemaEntry / ConfigValueTypePresets de configuração, a config resolvida, e o esquema de tipo por chave.
LocalesFile / SkinsFile / ConfigurationsFileO objeto de nível superior de cada arquivo dividido .caputchin/<axis>.json.
MarketplaceMetadata / PreferredPresentationO bloco marketplace e a dica de pegada preferred.

Crie um arquivo dividido com um import satisfies para que o compilador o cheque:

import type { LocalesFile } from "@caputchin/game-sdk";
export default { schema: { /* ... */ }, presets: { /* ... */ } } satisfies LocalesFile;

O que está intencionalmente ausente

  • Nenhum sessionId ou identificador de plataforma chega ao jogo.
  • Nenhum gancho de ciclo de vida start / pause / resume; a chamada da fábrica é o início.
  • Nenhum maxScore ou faixa de pontuação da plataforma; a pontuação do veredito é o que o seu run retornar.

O contrato é intencionalmente minúsculo para que continue estável ao longo de anos de crescimento do catálogo.

Veja também

Nesta página