# 用 catalogue.json 和 .play 打包 PlayDrop 遊戲

安排根目錄含 catalogue.json 的建置遊戲資料夾、ZIP 或 .play，宣告上架媒體與伺服器，並用 prepare_catalogue_upload 上傳。

Source: https://www.playdrop.ai/zh-hant/create/learn/packaging

套件是遊戲的建置輸出，加上描述它的 `catalogue.json`。所有 PlayDrop 功能都要透過套件：多個檔案、SDK、上架圖片與影片、排行榜、成就、素材和託管伺服器。從你的 AI App 以資料夾、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` 檔案就是把這個資料夾壓縮起來，`catalogue.json` 位於壓縮檔的根目錄（而不是包在另一個資料夾裡），再將副檔名改為 `.play`。它只包含建置後的檔案：不要有 `node_modules`、你不想公開的 source map，或 `.env` 檔案。原始專案請留在你的使用者那裡；PlayDrop 無法傳回它。

## 撰寫 catalogue.json

```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` 是啟動遊戲的頁面的確切路徑。若未設定，入口預設為 `<name>.html`，而不是 `index.html`。
- 同一款遊戲每次上傳時，`version` 都要是新的語意化版本。
- `surfaceTargets` 列出你測試過的顯示環境；`primarySurface` 是遊戲設計時採用的顯示環境。
- 上架媒體、成就圖示和伺服器入口都由目錄認領：`listing/` 底下沒有任何欄位參照的檔案不是上架媒體，而沒有任何遊戲認領的檔案會在發布任何內容之前被拒絕。
- `server.entry` 指向一個建置好的 ES 模組打包檔；請參閱[即時遊戲伺服器](https://www.playdrop.ai/zh-hant/create/learn/game-servers)。

所有欄位及其限制都列在 [catalogue.json 參考](https://www.playdrop.ai/zh-hant/create/learn/catalogue-json)中。沒有需要設定的目錄版本欄位。

## 上傳資料夾

傳送 `prepare_catalogue_upload`，附上新的 `requestId`、`expectedCurrentVersion`（新遊戲為 `null`）、完整的目錄物件，以及每個檔案一個描述項。小型文字檔可以使用內嵌的 `text`。其他每個檔案都是簽名上傳：請在本機根據確切的位元組計算它的大小、SHA-256（64 個小寫十六進位字元）和 base64 MD5。下面這個兩檔案遊戲的請求是完整的；請將圖示上的兩個摘要預留值換成圖示的真實值。

```json
{
  "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` 的上傳網址和標頭。將圖示的確切位元組連同每個傳回的標頭 PUT 到該網址，然後以相同的 `requestId` 呼叫 `complete_catalogue_upload`。回執的 `url` 會開啟私人版本。

## 上傳 ZIP 或 .play

- **有檔案系統的代理**會在本機解壓縮壓縮檔，然後如上所述以資料夾上傳。
- **ChatGPT** 會將它從對話中解析出的壓縮檔作為 `archive` 傳入，附上真正的 `download_url` 和 `file_id`，不附 `catalogue` 或 `files`。壓縮後最多 20 MiB。

壓縮檔必須是一般的 ZIP 檔：不得加密、分成多個磁碟區、使用 ZIP64、包含符號連結、重複路徑、絕對路徑或 `..`。空檔案和巢狀的 catalogue.json 檔案會被拒絕。

## 限制

512 個檔案或壓縮檔項目（包括 catalogue.json 和資料夾）、每個檔案 50 MiB、解壓縮後 200 MiB，以及 1 MiB 的目錄 JSON。託管伺服器打包檔最多 2 MiB。

## 更新套件

讀取 `list_games`，保留每款遊戲的 `name`，提高它的 `version`，並將 `expectedCurrentVersion` 設為目前發布的版本。傳送完整快照：新版本應包含的每個檔案和欄位。保留版本中未變更的檔案，可以用 `reuse: { gameId, version, path }` 傳送，而不必傳送它們的位元組。排行榜和成就的鍵無法移除，也無法變更類型；請用 `"status": "RETIRED"` 停用。

## 連接器目前還無法上傳的素材

PlayDrop 會在自己的工具中執行可執行的 3D 模型（`procedural` 子類別或 `CUSTOM` 格式的 `MODEL_3D` 素材），但連接器會拒絕它們，因為 API 無法驗證它們的程式碼。請將它們烘焙成支援的格式，或參照已在 PlayDrop 上發布的素材。烘焙後的程序化圖片和精靈圖表可以接受。請參閱[遊戲素材](https://www.playdrop.ai/zh-hant/create/learn/game-assets)。

## 相關指南

- [catalogue.json](https://www.playdrop.ai/zh-hant/create/learn/catalogue-json): PlayDrop 遊戲使用的 catalogue.json 欄位：身分、上架資訊、遊玩方式、顯示環境、登入、即玩、預先載入、媒體、翻譯、分數與伺服器。
- [從你的 AI App 發布](https://www.playdrop.ai/zh-hant/create/learn/mcp-publishing): AI 代理如何透過 MCP 發布到 PlayDrop：簡易方式與套件方式、私人測試、publish_game_version、更新、限制與復原。
- [上架圖片與影片](https://www.playdrop.ai/zh-hant/create/learn/listing-assets): PlayDrop 遊戲可以有哪些上架圖片與影片、它們的路徑、格式與方向，以及如何製作在動態、搜尋和連結預覽中都好看的圖片。
- [即時遊戲伺服器](https://www.playdrop.ai/zh-hant/create/learn/game-servers): 為你的遊戲執行附帶 MongoDB 資料庫的託管 Colyseus 0.17 伺服器，用 SDK 從瀏覽器連線，用兩位玩家測試，並了解各項限制。
