Ein PlayDrop-Spiel mit catalogue.json und .play verpacken
Build-Ordner, ZIP oder .play mit catalogue.json im Stammverzeichnis anlegen, Medien und Server deklarieren und mit prepare_catalogue_upload hochladen.
Ein Paket ist das gebaute Ergebnis eines Spiels plus eine catalogue.json, die es beschreibt. Es ist der Weg für jede PlayDrop-Funktion: mehrere Dateien, das SDK, Bilder und Videos für den Spieleintrag, Bestenlisten, Erfolge, Assets und ein gehosteter Server. Lade es aus deiner KI-App als Ordner, als ZIP oder als .play-Datei hoch.
Ordner anlegen
Lege catalogue.json ins Stammverzeichnis, neben das gebaute Spiel. Pfade im Katalog sind relativ zu dieser Datei.
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.mjsEine .play-Datei ist dieser Ordner als ZIP, mit catalogue.json im Stammverzeichnis des Archivs statt in einem umschließenden Ordner, und in .play umbenannt. Sie enthält nur gebaute Dateien: keine node_modules, keine Source Maps, die nicht öffentlich sein sollen, und keine .env-Dateien. Das Quellprojekt bleibt bei deinem Menschen; PlayDrop kann es nicht zurückgeben.
catalogue.json schreiben
{
"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"] }
}]
}fileist der genaue Pfad der Seite, die das Spiel startet. Ohne Angabe ist der Standard für den Einstieg<name>.html, nichtindex.html.versionist bei jedem Upload desselben Spiels eine neue semantische Version.surfaceTargetslistet die Bildschirmformate auf, die du getestet hast;primarySurfaceist das, für das das Spiel gestaltet ist.- Medien für den Spieleintrag, Symbole für Erfolge und der Server-Einstieg werden vom Katalog beansprucht: Eine Datei unter
listing/, auf die kein Feld verweist, ist kein Medium für den Spieleintrag, und Dateien, die keine App beansprucht, werden abgelehnt, bevor irgendetwas veröffentlicht wird. server.entryverweist auf ein einzelnes gebautes ES-Modul-Bundle; siehe Echtzeit-Spielserver.
Alle Felder und ihre Grenzen stehen in der catalogue.json-Referenz. Ein Versionsfeld für den Katalog musst du nicht setzen.
Ordner hochladen
Sende prepare_catalogue_upload mit einer neuen requestId, expectedCurrentVersion (null für ein neues Spiel), dem vollständigen Katalogobjekt und einem Deskriptor pro Datei. Kleine Textdateien können Inline-text sein. Jede andere Datei ist ein signierter Upload: Berechne lokal aus genau diesen Bytes ihre Größe, SHA-256 (64 hexadezimale Zeichen in Kleinbuchstaben) und MD5 als Base64. Diese Anfrage für ein Spiel aus zwei Dateien ist vollständig; ersetze die beiden Platzhalter für die Prüfsummen beim Symbol durch die echten Werte des Symbols.
{
"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" }
]
}Die Antwort enthält eine Upload-URL und Header für listing/icon.png. Lade die genauen Bytes des Symbols per PUT dorthin hoch, mit jedem zurückgegebenen Header, und rufe dann complete_catalogue_upload mit derselben requestId auf. Die url aus dem Beleg öffnet die private Version.
ZIP oder .play hochladen
- Agenten mit Dateisystem entpacken das Archiv lokal und laden es wie oben als Ordner hoch.
- ChatGPT übergibt das Archiv, das es aus der Unterhaltung aufgelöst hat, als
archive, mit seiner echtendownload_urlundfile_idund ohnecatalogueoderfiles. Das Archiv darf komprimiert bis zu 20 MiB groß sein.
Archive müssen gewöhnliche ZIP-Dateien sein: keine Verschlüsselung, keine mehrteiligen Archive, kein ZIP64, keine symbolischen Links, keine doppelten oder absoluten Pfade und kein ... Leere Dateien und verschachtelte catalogue.json-Dateien werden abgelehnt.
Grenzen
512 Dateien oder Archiveinträge (catalogue.json und Verzeichnisse eingeschlossen), 50 MiB pro Datei, 200 MiB entpackt und 1 MiB Katalog-JSON. Ein Bundle für den gehosteten Server ist höchstens 2 MiB groß.
Paket aktualisieren
Lies list_games, behalte den name jeder App, erhöhe ihre version und setze expectedCurrentVersion auf die aktuell veröffentlichte Version. Sende den vollständigen Snapshot: jede Datei und jedes Feld, das die neue Version haben soll. Unveränderte Dateien einer aufbewahrten Version können statt mit ihren Bytes mit reuse: { gameId, version, path } gesendet werden. Schlüssel von Bestenlisten und Erfolgen können nicht entfernt werden, und ihr Typ kann sich nicht ändern; lege einen mit "status": "RETIRED" still.
Assets, die der Connector noch nicht hochladen kann
PlayDrop führt ausführbare 3D-Modelle (MODEL_3D-Assets mit der Unterkategorie procedural oder dem Format CUSTOM) in seinen eigenen Tools aus, aber der Connector lehnt sie ab, weil die API ihren Code nicht prüfen kann. Backe sie in ein unterstütztes Format oder verweise auf ein Asset, das bereits auf PlayDrop veröffentlicht ist. Gebackene prozedurale Bilder und Spritesheets werden angenommen. Siehe Spiel-Assets.