Custom asset formats and player creations on PlayDrop
Define your own asset format with an asset spec, declare the formats a game reads or writes, and let players save and publish creations with sdk.assets.custom.
Asset specs let a game define its own kind of asset, such as a level, a character or a deck, as a contract of files. Players can then make, save and publish creations in that format, and other games that support it can open them.
Define an asset spec
An asset spec is declared in the assetSpecs list of catalogue.json, next to apps:
{
"assetSpecs": [{
"name": "moon-level",
"version": "1.0.0",
"displayName": "Moon Jump level",
"symbol": "specs/moon-level.svg",
"contract": "specs/moon-level.contract.json"
}]
}The contract names the files of each asset and how to check them:
{
"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" }
]
}Roles may carry a JSON Schema, which PlayDrop checks on every save. Publish a new spec version when the format changes; old assets keep their version.
Declare what a game supports
{
"assetSpecSupport": [
{ "assetSpec": "asset-spec:your-name/moon-level", "versionRange": "^1.0.0", "capabilities": ["READ", "WRITE"] }
]
}Capabilities are READ, WRITE, EDIT, PREVIEW and IMPORT.
Save and load player creations
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 }saveDraftkeeps a private draft;publishmakes it public. Both need the complete set of files.- Asset references look like
asset:creator/name@r2.loadJson,loadTextanddownloadFileread published assets;loadOwned,loadOwnedJsonandloadOwnedFileread the player's own, drafts included. supports(versionRef, capability)checks before opening an asset from another version.- Errors use codes such as
custom_asset_capability_unsupportedandcustom_asset_role_type_mismatch.
Players need to be signed in to save. Review what players publish the way you would any user content: PlayDrop's content policy applies to it.
What the connector accepts
Data-only custom assets and specs upload like other files. Executable models, meaning MODEL_3D assets with the procedural subcategory or the CUSTOM format, are refused by the connector because the API does not run creator code; bake them or reference a published version. See game assets.