Empaqueta un juego de PlayDrop con catalogue.json y .play
Organiza una carpeta, ZIP o .play compilado con catalogue.json en la raíz, declara medios de la ficha y servidores, y súbelo con prepare_catalogue_upload.
Un paquete es el resultado compilado de un juego más un catalogue.json que lo describe. Es la vía para todas las funciones de PlayDrop: varios archivos, el SDK, imágenes y vídeos de la ficha, clasificaciones, logros, recursos y un servidor alojado. Súbelo desde tu app de IA como carpeta, como ZIP o como archivo .play.
Organiza la carpeta
Pon catalogue.json en la raíz, junto al juego compilado. Las rutas del catálogo son relativas a él.
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.mjsUn archivo .play es esta carpeta comprimida en ZIP con catalogue.json en la raíz del archivo, no dentro de una carpeta contenedora, y renombrada a .play. Solo contiene archivos compilados: ni node_modules, ni mapas de código fuente que no quieras hacer públicos, ni archivos .env. El proyecto fuente se queda con tu usuario; PlayDrop no puede devolverlo.
Escribe 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"] }
}]
}filees la ruta exacta de la página que inicia el juego. Sin ella, la entrada es<name>.htmlpor defecto, noindex.html.versiones una nueva versión semántica en cada subida del mismo juego.surfaceTargetsenumera las pantallas que has probado;primarySurfacees aquella para la que está diseñado el juego.- Las imágenes y vídeos de la ficha, los iconos de los logros y la entrada del servidor los reclama el catálogo: un archivo dentro de
listing/al que ningún campo hace referencia no forma parte de la ficha, y los archivos que ninguna app reclama se rechazan antes de publicar nada. server.entryapunta a un único módulo ES compilado; consulta servidores de juego en tiempo real.
Todos los campos y sus límites están en la referencia de catalogue.json. No hay que indicar ningún campo de versión del catálogo.
Sube una carpeta
Envía prepare_catalogue_upload con un nuevo requestId, expectedCurrentVersion (null para un juego nuevo), el objeto completo del catálogo y un descriptor por archivo. Los archivos de texto pequeños pueden ir como text en línea. Todos los demás archivos son subidas firmadas: calcula en local su tamaño, su SHA-256 (64 caracteres hexadecimales en minúsculas) y su MD5 en base64 a partir de los bytes exactos. Esta solicitud para un juego de dos archivos está completa; sustituye los dos marcadores de resumen del icono por sus valores reales.
{
"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" }
]
}La respuesta indica una URL de subida y unas cabeceras para listing/icon.png. Haz PUT de los bytes exactos del icono a esa URL con todas las cabeceras devueltas y, después, llama a complete_catalogue_upload con el mismo requestId. La url del recibo abre la versión privada.
Sube un ZIP o un .play
- Los agentes con sistema de archivos descomprimen el archivo en local y lo suben como carpeta, como se explica arriba.
- ChatGPT pasa como
archiveel archivo comprimido que resolvió de la conversación, con susdownload_urlyfile_idreales, y sincataloguenifiles. El archivo puede ocupar hasta 20 MiB comprimido.
Los archivos comprimidos deben ser ZIP normales: sin cifrado, varios volúmenes, ZIP64, enlaces simbólicos, rutas duplicadas, rutas absolutas ni ... Se rechazan los archivos vacíos y los catalogue.json anidados.
Límites
512 archivos o entradas de archivo comprimido (incluidos catalogue.json y los directorios), 50 MiB por archivo, 200 MiB descomprimidos y 1 MiB de JSON del catálogo. El módulo de un servidor alojado ocupa 2 MiB como máximo.
Actualiza un paquete
Lee list_games, conserva el name de cada app, sube su version y establece expectedCurrentVersion con la versión publicada actual. Envía la instantánea completa: todos los archivos y campos que deba tener la nueva versión. Los archivos sin cambios de una versión conservada se pueden enviar con reuse: { gameId, version, path } en lugar de sus bytes. Las claves de las clasificaciones y los logros no se pueden eliminar ni cambiar de tipo; retíralas con "status": "RETIRED".
Recursos que el conector todavía no puede subir
PlayDrop ejecuta modelos 3D ejecutables (recursos MODEL_3D con la subcategoría procedural o el formato CUSTOM) en sus propias herramientas, pero el conector los rechaza porque la API no puede validar su código. Hornéalos en un formato compatible o haz referencia a un recurso ya publicado en PlayDrop. Se aceptan las imágenes y hojas de sprites procedurales ya horneadas. Consulta recursos de juego.