# PlayDrop의 사용자 지정 에셋 형식과 플레이어 창작물

에셋 사양으로 나만의 에셋 형식을 정의하고, 게임이 읽고 쓰는 형식을 선언하고, sdk.assets.custom으로 플레이어가 레벨, 캐릭터 등 창작물을 저장하고 게시하게 하세요.

Source: https://www.playdrop.ai/ko/create/learn/custom-assets

에셋 사양을 사용하면 게임이 레벨, 캐릭터, 덱 같은 고유한 종류의 에셋을 파일 계약으로 정의할 수 있습니다. 그러면 플레이어가 그 형식으로 창작물을 만들고 저장하고 게시할 수 있으며, 그 형식을 지원하는 다른 게임에서도 열 수 있습니다.

## 에셋 사양 정의하기

에셋 사양은 catalogue.json의 `apps` 옆에 있는 `assetSpecs` 목록에 선언합니다.

```json
{
  "assetSpecs": [{
    "name": "moon-level",
    "version": "1.0.0",
    "displayName": "Moon Jump level",
    "symbol": "specs/moon-level.svg",
    "contract": "specs/moon-level.contract.json"
  }]
}
```

계약에는 각 에셋을 이루는 파일과 그 파일을 검사하는 방법을 적습니다.

```json
{
  "primaryRole": "level",
  "roles": [
    { "name": "level", "required": true, "contentTypes": ["application/json"], "mode": "TEXT",
      "jsonSchema": { "type": "object", "required": ["tiles"], "properties": { "tiles": { "type": "array" } } } },
    { "name": "thumbnail", "required": false, "contentTypes": ["image/png"], "mode": "BINARY" }
  ]
}
```

역할에는 JSON Schema를 붙일 수 있으며, PlayDrop은 저장할 때마다 이를 검사합니다. 형식이 바뀌면 새 사양 버전을 게시하세요. 기존 에셋은 원래 버전을 유지합니다.

## 게임이 지원하는 형식 선언하기

```json
{
  "assetSpecSupport": [
    { "assetSpec": "asset-spec:your-name/moon-level", "versionRange": "^1.0.0", "capabilities": ["READ", "WRITE"] }
  ]
}
```

기능은 `READ`, `WRITE`, `EDIT`, `PREVIEW`, `IMPORT`가 있습니다.

## 플레이어 창작물 저장하고 불러오기

```js
const levels = sdk.assets.custom.forSpec("asset-spec:your-name/moon-level");

await levels.saveDraft({ assetName: "crater-run", displayName: "Crater run",
  files: { level: new Blob([JSON.stringify(level)], { type: "application/json" }) } });
await levels.publish({ assetName: "crater-run", displayName: "Crater run", files: { level: levelBlob, thumbnail: pngBlob } });

const mine = await levels.listMine();
const latest = mine[0]?.latestPublicVersion;
if (latest) startLevel(await levels.loadJson({ assetRef: latest.assetRef, role: "level" }));

const community = await levels.listPublic({ limit: 20 }); // { assets, pagination }
```

- `saveDraft`는 비공개 초안을 보관하고, `publish`는 이를 공개합니다. 둘 다 전체 파일 세트가 필요합니다.
- 에셋 참조는 `asset:creator/name@r2` 형태입니다. `loadJson`, `loadText`, `downloadFile`은 게시된 에셋을 읽고, `loadOwned`, `loadOwnedJson`, `loadOwnedFile`은 초안을 포함해 플레이어 본인의 에셋을 읽습니다.
- 다른 버전의 에셋을 열기 전에 `supports(versionRef, capability)`로 확인하세요.
- 오류에는 `custom_asset_capability_unsupported`, `custom_asset_role_type_mismatch` 같은 코드가 쓰입니다.

저장하려면 플레이어가 로그인해야 합니다. 플레이어가 게시하는 콘텐츠는 다른 사용자 콘텐츠와 똑같이 검토하세요. PlayDrop의 콘텐츠 정책이 적용됩니다.

## 커넥터가 받는 것

데이터만 담은 사용자 지정 에셋과 사양은 다른 파일처럼 업로드됩니다. 실행 가능한 모델, 즉 `procedural` 하위 카테고리나 `CUSTOM` 형식을 쓰는 `MODEL_3D` 에셋은 API가 크리에이터 코드를 실행하지 않으므로 커넥터가 거부합니다. 미리 일반 모델로 구워서 올리거나 게시된 버전을 참조하세요. [게임 에셋](https://www.playdrop.ai/ko/create/learn/game-assets)을 참고하세요.

## 관련 가이드

- [게임 에셋](https://www.playdrop.ai/ko/create/learn/game-assets): PlayDrop 게임에 이미지, 사운드, 동영상, 3D를 담아 보내세요. 포함 파일, catalogue.json에 선언한 게임 소유 에셋, 공개 에셋과 팩, sdk.assets 런타임 조회를 다룹니다.
- [catalogue.json](https://www.playdrop.ai/ko/create/learn/catalogue-json): PlayDrop 게임이 쓰는 catalogue.json 필드: 식별 정보, 등록 정보, 플레이 방식, 화면, 로그인, 인스턴트, 미리 로드, 미디어, 번역, 점수, 서버.
- [클라이언트 SDK](https://www.playdrop.ai/ko/create/learn/sdk): PlayDrop 브라우저 SDK 참조: 초기화, 호스트 수명 주기, 플레이어 신원과 저장, 기기와 컨트롤러, 소셜, 멀티플레이어, 상점, 광고, 순위표, 업적, 에셋, AI.
