Empacote um jogo do PlayDrop com catalogue.json e .play
Organize uma pasta, ZIP ou .play compilado com o catalogue.json na raiz, declare a mídia da listagem e os servidores e envie com prepare_catalogue_upload.
Um pacote é o resultado compilado de um jogo mais um catalogue.json que o descreve. É o caminho para todos os recursos do PlayDrop: vários arquivos, o SDK, imagens e vídeos da listagem, placares, conquistas, assets e um servidor hospedado. Envie-o pelo seu app de IA como uma pasta, um ZIP ou um arquivo .play.
Organize a pasta
Coloque o catalogue.json na raiz, ao lado do jogo compilado. Os caminhos no catálogo são relativos a ele.
catalogue.json
index.html
assets/sprites.png
assets/music.mp3
listing/icon.png
listing/hero-landscape.png
listing/hero-portrait.png
listing/screenshots/landscape-1.png
listing/videos/portrait-1.mp4
achievements/first-win.png
server/index.mjsUm arquivo .play é esta pasta compactada em ZIP, com o catalogue.json na raiz do arquivo, e não dentro de uma pasta extra, e renomeada para .play. Ele contém só arquivos compilados: nada de node_modules, de mapas de código-fonte que você não quer tornar públicos ou de arquivos .env. O projeto-fonte fica com a pessoa com quem você trabalha; o PlayDrop não pode devolvê-lo.
Escreva o catalogue.json
{
"apps": [{
"name": "moon-jump",
"displayName": "Moon Jump",
"subtitle": "Lunar platform hopping against the clock",
"description": "Jump between lunar platforms, collect oxygen and reach the flag.",
"controls": "Tap or press Space to jump. Swipe or use arrows to steer.",
"file": "index.html",
"version": "1.0.0",
"visibility": "PRIVATE",
"authMode": "OPTIONAL",
"tags": ["game-genre/casual", "game-genre/platformer"],
"types": ["solo"],
"controller": { "support": "optional", "type": "simpler" },
"surfaceTargets": { "desktop": true, "mobileLandscape": true, "mobilePortrait": true },
"primarySurface": "MOBILE_PORTRAIT",
"sourceLocale": "en",
"listing": {
"icon": "listing/icon.png",
"heroLandscape": "listing/hero-landscape.png",
"heroPortrait": "listing/hero-portrait.png",
"screenshotsLandscape": ["listing/screenshots/landscape-1.png"],
"videosPortrait": ["listing/videos/portrait-1.mp4"]
},
"leaderboards": [{ "key": "best-time", "displayName": "Best time", "description": "Fastest run to the flag",
"scoreType": "TIME_MS", "sort": "ASC" }],
"achievements": [{ "key": "first-win", "displayName": "First flag", "description": "Reach the flag once",
"kind": "STANDARD", "icon": "achievements/first-win.png" }],
"server": { "entry": "server/index.mjs", "rooms": ["game"] }
}]
}fileé o caminho exato da página que inicia o jogo. Sem ele, o padrão da entrada é<name>.html, e nãoindex.html.versioné uma nova versão semântica a cada envio do mesmo jogo.surfaceTargetslista as superfícies que você testou;primarySurfaceé aquela para a qual o jogo foi pensado.- A mídia da listagem, os ícones das conquistas e a entrada do servidor são reivindicados pelo catálogo: um arquivo em
listing/que nenhum campo referencia não é mídia da listagem, e os arquivos que nenhum app reivindica são recusados antes de qualquer publicação. server.entryaponta para um único módulo ES compilado e empacotado; veja servidores de jogo em tempo real.
Todos os campos e seus limites estão na referência do catalogue.json. Não há campo de versão do catálogo para definir.
Envie uma pasta
Envie prepare_catalogue_upload com um novo requestId, expectedCurrentVersion (null para um jogo novo), o objeto completo do catálogo e um descritor por arquivo. Arquivos de texto pequenos podem ir como text embutido. Todos os outros arquivos são envios assinados: calcule localmente o tamanho, o SHA-256 (64 caracteres hexadecimais minúsculos) e o MD5 em base64 a partir dos bytes exatos. Esta solicitação para um jogo de dois arquivos está completa; substitua os dois marcadores de resumo do ícone pelos valores reais dele.
{
"requestId": "moon-jump-1.0.0",
"expectedCurrentVersion": { "moon-jump": null },
"catalogue": {
"apps": [{
"name": "moon-jump",
"displayName": "Moon Jump",
"file": "index.html",
"version": "1.0.0",
"visibility": "PRIVATE",
"authMode": "OPTIONAL",
"tags": ["game-genre/casual"],
"types": ["solo"],
"controller": { "support": "off" },
"surfaceTargets": { "desktop": true, "mobileLandscape": false, "mobilePortrait": true },
"listing": { "icon": "listing/icon.png" }
}]
},
"files": [
{ "path": "index.html",
"text": "<!doctype html><html><head><meta charset=\"utf-8\"><title>Moon Jump</title></head><body><canvas id=\"game\"></canvas><script>/* built game */</script></body></html>" },
{ "path": "listing/icon.png", "contentType": "image/png", "sizeBytes": 50211,
"sha256": "REPLACE_WITH_ICON_SHA256_HEX", "md5Base64": "REPLACE_WITH_ICON_MD5_BASE64" }
]
}A resposta lista uma URL de envio e os cabeçalhos para listing/icon.png. Faça o PUT dos bytes exatos do ícone nessa URL, com todos os cabeçalhos retornados, e depois chame complete_catalogue_upload com o mesmo requestId. A url do recibo abre a versão privada.
Envie um ZIP ou .play
- Agentes com sistema de arquivos descompactam o arquivo localmente e o enviam como pasta, como acima.
- O ChatGPT passa como
archiveo arquivo compactado que resolveu a partir da conversa, com osdownload_urlefile_idreais, semcataloguenemfiles. O arquivo pode ter até 20 MiB compactado.
Os arquivos compactados precisam ser ZIPs comuns: sem criptografia, vários volumes, ZIP64, links simbólicos, caminhos duplicados, caminhos absolutos ou ... Arquivos vazios e arquivos catalogue.json aninhados são recusados.
Limites
512 arquivos ou entradas do arquivo compactado (incluindo o catalogue.json e os diretórios), 50 MiB por arquivo, 200 MiB descompactados e 1 MiB de JSON do catálogo. O módulo empacotado de um servidor hospedado tem no máximo 2 MiB.
Atualize um pacote
Leia list_games, mantenha o name de cada app, aumente a version dele e defina expectedCurrentVersion como a versão publicada atual. Envie a versão completa: todos os arquivos e campos que a nova versão deve ter. Os arquivos sem alterações de uma versão mantida podem ser enviados com reuse: { gameId, version, path } em vez dos bytes. As chaves de placares e conquistas não podem ser removidas nem mudar de tipo; aposente uma delas com "status": "RETIRED".
Assets que o conector ainda não consegue enviar
O PlayDrop roda modelos 3D executáveis (assets MODEL_3D com a subcategoria procedural ou o formato CUSTOM) nas próprias ferramentas, mas o conector os recusa porque a API não consegue validar o código deles. Converta-os em arquivos fixos (bake) em um formato compatível ou faça referência a um asset já publicado no PlayDrop. Imagens e spritesheets procedurais já convertidas são aceitas. Veja assets de jogo.