catalogue.json と .play で PlayDrop ゲームをパッケージ化する
ルートに catalogue.json を置いたビルド済みのフォルダー、ZIP、.play を用意し、掲載メディアとサーバーを宣言して、prepare_catalogue_upload でアップロードします。
パッケージとは、ゲームのビルド結果と、それを記述する catalogue.json をまとめたものです。複数のファイル、SDK、掲載用の画像と動画、ランキング、実績、アセット、ホスト型サーバーなど、PlayDrop のすべての機能を使うための方法です。AI アプリから、フォルダー、ZIP、.play ファイルとしてアップロードします。
フォルダーを構成する
ビルド済みのゲームと同じ場所、つまりルートに catalogue.json を置きます。カタログ内のパスは、このファイルからの相対パスです。
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.mjs.play ファイルは、このフォルダーを ZIP にして拡張子を .play に変えたものです。catalogue.json は、外側のフォルダーの中ではなく、アーカイブのルートに置きます。中身はビルド済みのファイルだけにしてください。node_modules、公開したくないソースマップ、.env ファイルは含めません。ソースプロジェクトはユーザーの手元に残してください。PlayDrop はそれを返すことができません。
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は、ゲームを開始するページの正確なパスです。省略すると、エントリーはindex.htmlではなく<name>.htmlになります。versionは、同じゲームをアップロードするたびに新しくするセマンティックバージョンです。surfaceTargetsにはテスト済みの表示環境を列挙し、primarySurfaceにはゲームが想定している表示環境を指定します。- 掲載メディア、実績のアイコン、サーバーのエントリーは、カタログから参照されることで使われます。
listing/内のファイルでも、どのフィールドからも参照されていないものは掲載メディアになりません。また、どのアプリからも参照されていないファイルがあると、何も公開される前に拒否されます。 server.entryは、ビルド済みの ES モジュールのバンドル1つを指します。リアルタイムゲームサーバーをご覧ください。
すべてのフィールドとその制限は、catalogue.json リファレンスにあります。設定が必要なカタログのバージョンフィールドはありません。
フォルダーをアップロードする
新しい requestId、expectedCurrentVersion(新しいゲームなら null)、完全なカタログのオブジェクト、ファイルごとに1つの記述子を指定して、prepare_catalogue_upload を送信します。小さなテキストファイルはインラインの text にできます。それ以外のファイルはすべて署名付きアップロードです。サイズ、SHA-256(64文字の小文字の16進数)、base64 の MD5 を、ローカルで実際のバイトから正確に計算してください。次のリクエストは、2ファイルのゲームの完全な例です。アイコンの2つのダイジェストのプレースホルダーを、アイコンの実際の値に置き換えてください。
{
"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" }
]
}レスポンスには、listing/icon.png 用のアップロード URL とヘッダーが含まれます。返されたすべてのヘッダーを付けて、アイコンの実際のバイトをそこに PUT し、同じ requestId で complete_catalogue_upload を呼び出します。アップロード結果の url を開くと、非公開バージョンが表示されます。
ZIP または .play をアップロードする
- ファイルシステムを使えるエージェントは、アーカイブをローカルで展開し、上と同じようにフォルダーとしてアップロードします。
- ChatGPT は、会話から解決したアーカイブを、本物の
download_urlとfile_id付きでarchiveとして渡し、catalogueとfilesは指定しません。アーカイブは圧縮後で最大 20 MiB まで使えます。
アーカイブは普通の ZIP ファイルである必要があります。暗号化、複数ボリューム、ZIP64、シンボリックリンク、パスの重複、絶対パス、.. は使えません。空のファイルや、入れ子になった catalogue.json ファイルは拒否されます。
制限
ファイルまたはアーカイブのエントリーは512個まで(catalogue.json とディレクトリを含む)、1ファイルあたり 50 MiB、展開後 200 MiB、カタログの JSON は 1 MiB までです。ホスト型サーバーのバンドルは最大 2 MiB です。
パッケージを更新する
list_games を読み取り、各アプリの name を維持して version を上げ、expectedCurrentVersion に現在の公開バージョンを設定します。完全なスナップショット、つまり新しいバージョンに含めるべきすべてのファイルとフィールドを送信してください。保持されているバージョンの変更していないファイルは、バイトの代わりに reuse: { gameId, version, path } で送れます。ランキングと実績のキーは削除できず、種類も変更できません。終了するには "status": "RETIRED" を指定します。
コネクタでまだアップロードできないアセット
PlayDrop は、実行可能な 3D モデル(procedural サブカテゴリーまたは CUSTOM 形式の MODEL_3D アセット)を独自のツールで動かしますが、API がそのコードを検証できないため、コネクタでは拒否されます。対応している形式にベイクするか、PlayDrop ですでに公開されているアセットを参照してください。ベイク済みのプロシージャル画像やスプライトシートは受け付けます。ゲームアセットをご覧ください。