跳到主要内容
版本:v3

云存档开发指南

阅读此文档前请先阅读云存档功能介绍,了解云存档的核心概念及功能。

集成前准备

接入云存档的前提是:

  1. 绑定域名,包括 API 域名和文件域名。

  2. 云存档需要依赖于内建账户,因此需要通过开发者中心开通 TDS 内建账户。游戏存档会绑定在 TDSUser 下,所以请首先参考内建账户系统集成文档完成 SDK 获取SDK 初始化以及登录功能的接入。

创建存档

SDK 会自动获取当前登录玩家(TDSUser)信息,关联到存档上。 因此,用户已登录时才能创建存档。

var gameSave = new TapGameSave
{
Name = "internal name",
Summary = "description",
ModifiedAt = DateTime.Now.ToLocalTime(),
PlayedTime = 60000L, // ms
ProgressValue = 100,
CoverFilePath = image_local_path, // jpg/png
GameFilePath = dll_local_path
};
await gameSave.Save();

上面的例子中,存档元信息字段的含义请参考云存档保存的游戏元数据。 保存时,SDK 会限制仅当前玩家可以读写存档本身及关联的存档文件、封面文件。

查询用户存档

最常见的场景是获取当前玩家的所有存档:

var collection = await TapGameSave.GetCurrentUserGameSaves();

foreach(var gameSave in collection){
var summary = gameSave.Summary;
var modifiedAt = gameSave.ModifiedAt;
var playedTime = gameSave.PlayedTime;
var progressValue = gameSave.ProgressValue;
var coverFile = gameSave.Cover;
var gameFile = gameSave.GameFile;
var gameFileUrl = gameFile.Url;
}

gameFile.Url 是保存在云端的存档文件的下载地址,通过这个 URL 下载的文件格式和上传时的格式保持一致。

当然也可以查询满足特定条件的存档,比如查询当前玩家游戏进度超过第 3 关的存档:

TDSUser user = await TDSUser.GetCurrent();
LCQuery<TapGameSave> gameSaveQuery = TapGameSave.GetQueryWithUser(user);
gameSaveQuery.WhereGreaterThan("progressValue", 3);
var collections = await gameSaveQuery.Find();

查询条件的构造请参考数据存储指南查询章节的说明

注意,如果之前整个游戏的任意玩家从未保存过存档,那么查询存档会报错 Class or object doesn't exists. 这是因为云存档在底层数据库层面的表(Class)只在保存第一个存档时才会创建。

删除用户存档

玩家只能删除自己的存档。

删除存档:

await gameSave.Delete();

删除存档时云端会自动删除关联的封面文件和存档原文件。

REST API

下面我们介绍云存档相关的 REST API 接口。 开发者可以自行编写程序或脚本调用这些接口在服务端进行管理性质的操作。

请求格式

对于 POST 和 PUT 请求,请求的主体必须是 JSON 格式,而且 HTTP Header 的 Content-Type 需要设置为 application/json

请求的鉴权是通过 HTTP Header 里面包含的键值对来进行的,参数如下表:

KeyValue含义来源
X-LC-Id{{appid}}当前应用的 App Id(即 Client Id可在控制台查看
X-LC-Key{{appkey}}当前应用的 App Key(即 Client Token可在控制台查看
X-LC-Session<sessionToken>玩家的登录凭证

管理接口需要使用 Master KeyX-LC-Key: {{masterkey}},masterMaster KeyServer Secret,同样可在控制台查看。使用管理接口时无需携带 sessionToken

详见文档关于应用凭证的说明。

云存档限制只有添加存档的玩家本人可读可写,因此调用云存档的 REST API 接口时均需在 X-LC-Session HTTP 头中携带玩家的 sessionToken 或使用 Master Key,否则请求会因权限不足而失败。

Base URL

REST API 请求的 Base URL(下文 curl 示例中用 {{host}} 表示)即应用绑定的 API 自定义域名,可以在控制台绑定、查看。 详见文档关于域名的说明。

接口列表

接口名称接口请求方法接口地址接口描述
获取存档GET/gamesaves/:id根据 id 来获取存档记录
查询存档GET/gamesaves根据查询条件查询存档
添加存档POST/gamesaves增加新存档
更新存档PUT/gamesaves/:id根据 id 更新存档
删除存档DELETE/gamesaves/:id根据 id 删除文档

获取存档

curl -X GET \
-H "X-LC-Id: {{appid}}" \
-H "X-LC-Key: {{appkey}}" \
-H "X-LC-Session: <sessionToken>" \
https://API_BASE_URL/1.1/gamesaves/<objectId>

返回示例:

{
"updatedAt": "2021-08-16T09:18:30.093Z",
"progressValue": 123,
"name": "dennis",
"objectId": "611a2d65bcf94a3222b6d5f3",
"createdAt": "2021-08-16T09:18:29.761Z",
"gameFile": {
"__type": "Pointer",
"className": "_File",
"objectId": "60d1af149be3180684000002"
},
"summary": "hello",
"modifiedAt": {
"__type": "Date",
"iso": "2015-06-21T18:02:52.249Z"
},
"user": {
"__type": "Pointer",
"className": "_User",
"objectId": "5b62c15a9f54540062427acc"
}
}

各个字段的含义请参考云存档保存的游戏元数据

查询存档

可以通过 where 参数指定查询条件查询存档:

curl -X GET \
-H "X-LC-Id: {{appid}}" \
-H "X-LC-Key: {{appkey}}" \
-H "X-LC-Session: <sessionToken>" \
-H "Content-Type: application/json" \
-G \
--data-urlencode 'where={"progressValue":123}' \
https://API_BASE_URL/1.1/gamesaves

返回示例:

{
"results": [
{
"updatedAt": "2021-08-16T09:30:20.643Z",
"name": "dennis",
"createdAt": "2021-08-16T09:30:20.643Z",
"gameFile": {
"__type": "Pointer",
"className": "_File",
"objectId": "60d1af149be3180684000002"
},
"summary": "hello",
"modifiedAt": {
"__type": "Date",
"iso": "2015-06-21T18:02:52.249Z"
},
"objectId": "611a302cbcf94a3222b6d687"
}
]
}

where 的用法详见数据存储 REST API 指南

添加存档

添加存档时的必填字段和可选字段请参考云存档保存的游戏元数据

在调用添加存档接口前,请先创建 gameFilecover 指向的文件,并确保文件的 ACL 为仅限当前用户读取。

curl -X POST \
-H "X-LC-Id: {{appid}}" \
-H "X-LC-Key: {{appkey}}" \
-H "X-LC-Session: <sessionToken>" \
-H "Content-Type: application/json" \
-d '{
"progressValue":123,
"playedTime":1283490343,
"name":"dennis",
"gameFile":{"id":"55a39634e4b0ed48f0c1845c", "__type":"File"},
"cover":{"id": "543cbaede4b07db196f50f3c", "__type": "File"},
"summary":"hello",
"modifiedAt":{"__type":"Date", "iso":"2015-06-21T18:02:52.249Z"}
}' \
https://API_BASE_URL/1.1/gamesaves

成功创建时会返回 objectId 和创建时间:

{"objectId":"611a3407bcf94a3222b6d789", "createdAt":"2021-08-16T09:46:47.290Z"}

失败时会报错,例如:

  • gameFile is required.:遗漏了必填字段 gameFile
  • Forbidden to add new fields by class '_GameSave' permissions.:提交了非法字段,云存档目前暂不支持添加自定义字段。

删除存档

curl -X DELETE \
-H "X-LC-Id: {{appid}}" \
-H "X-LC-Key: {{appkey}}" \
-H "X-LC-Session: <sessionToken>" \
https://API_BASE_URL/1.1/gamesaves/<objectId>

会返回

{}

删除存档时也可以附加 where 条件,防止误删。 参见有条件删除对象

删除存档时云端会自动删除关联的封面文件和存档原文件。

更新存档

curl -X PUT \
-H "X-LC-Id: {{appid}}" \
-H "X-LC-Key: {{appkey}}" \
-H "X-LC-Session: <sessionToken>" \
-H "Content-Type: application/json" \
-d '{"progressValue": 114514}' \
https://API_BASE_URL/1.1/gamesaves/<objectId>

成功时返回 objectId 和更新时间:

{
"updatedAt": "2021-08-16T09:49:49.579Z",
"objectId": "611a34bdbcf94a3222b6d7af"
}

失败时会报错,例如:

  • Forbidden to add new fields by class '_GameSave' permissions.:提交了非法字段,云存档目前暂不支持添加自定义字段。

注意,更新封面文件和存档原文件后,原本关联的封面文件和存档原文件并不会一并删除。 这些文件需要另外删除。 所以一般建议通过删除存档后重新创建存档的方式「更新」存档,这个更新存档的接口主要供服务端在一些管理场景下使用。