From 4aadf7126617a065624aa707965a2eb68499abc4 Mon Sep 17 00:00:00 2001 From: xiaoyi Date: Tue, 30 Nov 2021 12:21:30 +0800 Subject: [PATCH] feat:update upm --- CHANGELOG.md | 170 ++++++++++++++++ CHANGELOG.md.meta | 3 + Documentation.meta | 8 + Documentation/README.md | 257 ++++++++++++++++++++++++ Documentation/README.md.meta | 7 + Plugins.meta | 8 + Plugins/TapTap.Bootstrap.deps.json | 233 +++++++++++++++++++++ Plugins/TapTap.Bootstrap.deps.json.meta | 7 + Plugins/TapTap.Bootstrap.dll | Bin 0 -> 28672 bytes Plugins/TapTap.Bootstrap.dll.meta | 33 +++ Plugins/TapTap.Bootstrap.pdb | Bin 0 -> 14088 bytes Plugins/TapTap.Bootstrap.pdb.meta | 7 + README.md | 254 +++++++++++++++++++++++ README.md.meta | 3 + VERSIONNOTE.md | 6 + VERSIONNOTE.md.meta | 7 + package.json | 14 ++ package.json.meta | 7 + 18 files changed, 1024 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 CHANGELOG.md.meta create mode 100644 Documentation.meta create mode 100644 Documentation/README.md create mode 100644 Documentation/README.md.meta create mode 100644 Plugins.meta create mode 100644 Plugins/TapTap.Bootstrap.deps.json create mode 100644 Plugins/TapTap.Bootstrap.deps.json.meta create mode 100644 Plugins/TapTap.Bootstrap.dll create mode 100644 Plugins/TapTap.Bootstrap.dll.meta create mode 100644 Plugins/TapTap.Bootstrap.pdb create mode 100644 Plugins/TapTap.Bootstrap.pdb.meta create mode 100644 README.md create mode 100644 README.md.meta create mode 100644 VERSIONNOTE.md create mode 100644 VERSIONNOTE.md.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3f30391 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,170 @@ +# ChangeLog + +## 3.5.0 + +### Dependencies + +- TapTap.Login v3.5.0 +- TapTap.Common v3.5.0 +- LeanCloud.Realtime v0.10.0 +- LeanCloud.Storage v0.10.0 + +## 3.4.0 + +### Dependencies + +- TapTap.Login v3.4.0 +- TapTap.Common v3.4.0 +- LeanCloud.Realtime v0.10.0 +- LeanCloud.Storage v0.10.0 + +## 3.3.0 + +### Dependencies + +- TapTap.Login v3.3.0 +- TapTap.Common v3.3.0 +- LeanCloud.Realtime v0.9.11 +- LeanCloud.Storage v0.9.11 + +## 3.2.0 + +### New Feature + +- 支持云存档 + +### Dependencies + +- TapTap.Login v3.2.0 +- TapTap.Common v3.2.0 +- LeanCloud.Storage v0.9.5 +- LeanCloud.Realtime v0.9.5 + +## 3.1.0 + +### New Feature + +- `TDSUser` 新增好友系统操作 + +### Dependencies + +- TapTap.Login v3.1.0 +- TapTap.Common v3.1.0 +- LeanCloud.Storage v0.9.2 +- LeanCloud.Realtime v0.9.2 + +## 3.0.0 + +TapSDK 3.0 开始,我们在单纯的 TapTap 登录之外,还提供了一个内建账户系统供游戏使用:开发者可以直接用 TapTap OAuth +授权的结果生成一个游戏内的账号(TDSUser),然后用该账号保存更多玩家数据。同时,我们也支持将更多第三方认证登录的结果绑定到这一账号上来(以及后续的解绑操作)。 + +### New Feature + +- 新增 `TDSUser` 用于内建账户系统操作 + +### BreakingChange + +- `TapBootstrap` 接口仅保留 `TapBootstrap.Init(tapConfig)` 接口 + +### Dependencies + +- LeanCloud.Storage v0.8.2 +- TapTap.Login v3.0.0 +- TapTap.Common v3.0.0 + +## 2.1.7 + +### Dependencies + +- TapTap.Common v2.1.7 + +## 2.1.6 + +### Dependencies + +- TapTap.Common v2.1.6 + +## 2.1.5 + +### Dependencies + +- TapTap.Common v2.1.5 + +## 2.1.4 + +### Optimization and fixed bugs + +- 优化多语言相关 + +### Dependencies + +- TapTap.Common v2.1.4 + +## 2.1.3 + +### Feature + +* 新增繁中、日文、韩文、泰文和印尼语多语言配置 + +## 2.1.2 + +### BreakingChange + +* 废弃 OpenUserCenter 接口 + +### Dependencies + +* TapTap.Common v2.1.2 + +## 2.1.1 + +### Feature + +* 新增篝火测试资格校验 + ``` + TapBootstrap.GetTestQualification((bool, error)=>{ }): + ``` +* 通过 TapConfig 进行初始化配置 + * 新增 TapDBConfig 用于 TapDB 初始化配置 + * 新增 ClientSecret 用于 TapSDK 初始化 + ```c# + //建议使用以下 TapConfig 构造方法进行初始化 + var config = new TapConfig.Builder() + .ClientID("client_id") + .ClientSecret("client_secret") + .RegionType(RegionType.CN) + .TapDBConfig(true, "gameChannel", "gameVersion", true) + .ConfigBuilder(); + TapBootstrap.Init(config); + ``` + +### Breaking changes + +* LoginType 删除 Apple、Guest 登陆方式 +* TDS-Info.plist 删除 Apple_SignIn_Enable 配置 +* 废弃 Bind 接口 +* TapConfig 构造方法参数修改 + +### Dependencies + +* TapTap.Common v2.1.1 + +## 2.1.0 + +### Feature + +* 支持性改动用于 TapTap.Friends + +### Dependencies + +* TapTap.Common v2.1.0 + +## 2.0.0 + +### Feature + +* TapTap Bootstrap + +### Dependencies + +* TapTap.Common v2.0.0 \ No newline at end of file diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta new file mode 100644 index 0000000..419383c --- /dev/null +++ b/CHANGELOG.md.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7388165be5344a9682382768c5fce466 +timeCreated: 1616755935 \ No newline at end of file diff --git a/Documentation.meta b/Documentation.meta new file mode 100644 index 0000000..1130a03 --- /dev/null +++ b/Documentation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bd03b50332353477c899419b5b455fb0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Documentation/README.md b/Documentation/README.md new file mode 100644 index 0000000..2564c0c --- /dev/null +++ b/Documentation/README.md @@ -0,0 +1,257 @@ +# 使用 TapTap.Bootstrap + +## 使用前提 + +使用 TapTap.Bootstrap 前提是必须依赖以下库: +* [TapTap.Common](https://github.com/TapTap/TapCommon-Unity.git) +* [TapTap.Login](https://github.com/TapTap/TapLogin-Unity.git) +* [LeanCloud.Storage](https://github.com/leancloud/csharp-sdk) +* [LeanCloud.RealTime](https://github.com/leancloud/csharp-sdk) + +## 命名空间 + +```c# +using TapTap.Bootstrap; +``` + +## 接口描述 + +## 1.初始化 + +TapBootstrap 会根据 TapConfig 中的 TapDBConfig 配置来进行 TapDB 的自动初始化。 + +### 开启 TapDB +```c# +var config = new TapConfig.Builder() + .ClientID("client_id") + .ClientToken("client_token") + .ServerURL("https://ikggdre2.lc-cn-n1-shared.com") + .RegionType(RegionType.CN) + .TapDBConfig(true,"channel","gameVersion",true) + .Builder(); +``` +### 关闭 TapDB +```c# +var config = new TapConfig.Builder() + .ClientID("client_id") + .ClientToken("client_token") + .ServerURL("https://ikggdre2.lc-cn-n1-shared.com") + .RegionType(RegionType.CN) +//# .TapDBConfig(false,null,null,false) + .EnableTapDB(false) + .Builder(); +``` +### 初始化 +```c# +TapBootstrap.Init(config); +``` + +## 2.账户系统 + +> 登陆成功之后,都会得到一个 `TDSUser` 实例 + +### 使用 TapTap OAuth 授权结果直接登陆/注册账户系统 + +```c# +var tdsUser = await TDSUser.LoginWithTapTap(); +``` + +### 游客登陆 + +```c# +var tdsUser = await TDSUser.LoginAnonymously(); +``` + +### 使用第三方平台授权登录/注册账户 + +```c# +var tdsUser = await TDSUser.LoginWithAuthData(Dictionary authData, string platform, +LCUserAuthDataLoginOption option = null); +``` + +### 绑定第三方平台授权 + +```c# +await TDSUser.AssociateAuthData(Dictionary authData, string platform); +``` + +### 退出登陆 + +```c# +TDSUser.Logout(); +``` + +## 3.好友系统 + +### 申请成为好友 + +```c# +TDSUser tom, jerry; +await tom.ApplyFriendship(jerry); +``` +申请成功的回调中,我们会得到一个 LCFriendshipRequest 的实例,这个实例中包含了两个用户: +- sourceUser,指请求的发起方,上面的例子中就是 `tom`。 +- friend,指请求的目的方,上面的例子中就是 `jerry`。 + +tom 也可以在申请好友的时候,添加更多的属性,例如 tom 希望加 jerry 为好友的时候,也设定一个名为 cat 的圈子,可以这样操作: + +```cs +Dictionary attrs = new Dictionary { + { "group", "cat" } +}; +await tom.ApplyFriendship(jerry, attrs); +``` + +### 获取好友申请列表 +好友申请有三种状态: + +- `pending`,对方没有回应,还处于等待中。 +- `accepted`,对方已经接受,现在双方成为好友。 +- `declined`,对方已经拒绝。 + +好友请求创建之后默认是 `pending` 状态。 + +jerry 这里可以通过 `friendshipRequestQuery` 来查找不同状态的请求。例如 jerry 想看看新的好友请求,可以这样操作: + +```cs +LCQuery query = jerry.GetFriendshipRequestQuery(LCFriendshipRequest.STATUS_PENDING, false, true); +ReadOnlyCollection reqs = await query.Find(); +foreach (LCFriendshipRequest req in reqs) { + Console.WriteLine(req); +} +``` + +### 处理好友申请 + +jerry 对于新的好友请求,可以同意或者拒绝,也可以什么都不做,无视这些请求,甚至直接删除。这些操作我们都是支持的,请看下面的示例: + +```cs +LCFriendshipRequest tomRequest, tuffyRequest, otherRequest; +await jerry.AcceptFriendshipRequest(tomRequest); +await jerry.DeclineFriendshipRequest(tuffyRequest); +await jerry.DeleteFriendshipRequest(otherRequest); +``` + +注意: +* 在 jerry 拒绝了 tom 的好友请求之后,如果 tom 再次请求成为 jerry 的好友,tom 在执行 applyFriendshipInBackground 时会直接得到错误的应答,表明 jerry 不想和 ta 成为好友。 +* jerry 同意了 tuffy 的好友请求之后,它们就成为了好友,之后两个人中任何一人再次调用 applyFriendshipInBackground 申请横位好友时,也会直接得到错误的应答,表明它们已经是好友无需再次申请。 +* jerry 删除陌生人的好友请求后,对方还可以再次发起请求。 + +### 响应好友变化通知 + +TDS 好友模块支持客户端监听好友状态变化,在游戏中实时给玩家提示。好友状态变化的接口包括 + +```cs +public class FriendshipNotification { + public Action OnNewRequestComing { get; set; } + public Action OnRequestAccepted { get; set; } + public Action OnRequestDeclined { get; set; } +} +``` + +其中: +- onNewRequestComing 表示有其他人申请成为当前用户的好友,通过调用 `LCFriendshipRequest#getSourceUser()` 方法可以获得发起方用户信息。 +- onRequestAccepted 表示当前用户的好友申请被对方通过,通过调用 `LCFriendshipRequest#getFriend()` 方法可以获得对方用户信息。 +- onRequestDeclined 表示当前用户的好友申请被对方拒绝,通过调用 `LCFriendshipRequest#getFriend()` 方法可以获得对方用户信息。 + +开发者可以通过 `TDSUser#registerFriendshipNotification` 来注册通知接收器,通过调用 `TDSUser#unregisterFriendshipNotification` 来取消通知接收器。 + +### 获取好友列表 + +调用 `TDSUser#friendshipQuery()` 可以得到查询好友的 `LCQuery` 实例,之后调用 `LCQuery#findInBackground()` 方法就可以得到好友列表。示例如下: + +```cs +LCQuery query = jerry.GetFirendshipQuery(); +``` + +LCFriendship 里面会包含两个用户: + +- `LCFriendship#getLCUser(LCFriendship.ATTR_USER)` 得到的是 jerry 自己; +- `LCFriendship#getLCUser(LCFriendship.ATTR_FOLLOWEE)` 得到的就是另一方的用户信息。 + +### 删除好友 + +成为好友关系的两个用户,之后也可以单方面删除好友。例如 jerry 不想再和 tom 成为好友,那只需要在自己的好友列表中删除包含 tom 的那条 LCFriendship 记录即可: + +```cs +await friendship.Delete(); +``` + +### 查询好友关系 + +我们使用 LCQuery 可以单独查询两个用户是否为好友关系。 + +```cs +LCQuery query = jerry.GetFirendshipQuery(); +query.whereEqualTo("followee", tom); +int count = await query.Count(); +if (count > 0) { + // tom is a friend of jerry. +} else { + // tom isn't a friend of jerry. +} +``` + +这一查询是通过网络发送到服务端执行的,一般情况下,我们推荐开发者在游戏启动时拉取一次当前登录用户的好友列表,然后缓存在本地,以后需要检查另外玩家是否为当前用户的好友时,直接从缓存中查询即可。如果担心好友数据变化,缓存没有得到及时更新,可以调用前面「响应好友变化通知」的方法,对好友数据更新进行监听,这样在绝大部分时候数据同步都是可以保证的。 + +## 4.云存档 + +### 构建云存档元数据 + +```c# +var gameSave = new TapGameSave +{ + Name = "GameSave_Name",// 存档名称 + Summary = "GameSave_Description", // 该字段会作为展示给用户的实际存档名 + ModifiedAt = DateTime.Now.ToLocalTime(), // 原文件修改时间 + PlayedTime = 1000L, // 游戏时长,单位 ms (非必填) + ProgressValue = 100, // 游戏进度 ,单位 int (非必填) + CoverFilePath = pic, // 游戏封面,可以传入一个本地文件路径,SDK 限制为 png/jpeg 格式 + GameFilePath = dll // 存档源文件,可以传入一个本地文件路径 +}; + +``` +### 保存存档 + +保存存档时,会去检查当前`TDSUser`是否已经登录以及元数据。 + +同时 SDK 在上传时会去限制存档本身以及相关联的两个文件( Cover 以及 GameFile )的权限为当前用户本身。 +```c# +await gameSave.Save(); +``` + +### 查询当前用户的所有存档 + +```c# +var collection = await TapGameSave.GetCurrentUserGameSaves(); + +foreach(var gameSave in collection){ + // 存档概览 + var name = gameSave.Summary; + // 原文件修改时间 + var modifiedAt = gameSave.ModifiedAt; + // 游戏时长 + var playedTime = gameSave.PlayedTime; + // 游戏进度 + var progressValue = gameSave.ProgressValue; + // 游戏封面 + var coverFile = gameSave.CoverFile; + // 存档源文件 + var gameFile = gameSave.GameFile; + // 源文件下载地址 + var gameFileUrl = gameFile.Url; +} +``` + +### 查询当前用户存档 + +我们使用 `LCQuery` 来查询当前用户的云存档。 + +SDK 查询封装了一个限定方法用于查询当前`TDSUser`的云存档。 +```c# +TDSUser user = await TDSUser.GetCurrent(); +LCQuery gameSaveQuery = TapGameSave.GetQueryWithUser(user); +// 查询 Name 为 TDSUser_GameSave_Name 的云存档 +gameSaveQuery.WhereEqualTo("name","TDSUser_GameSave_Name"); +var collection = await gameSaveQuery.Find(); +``` \ No newline at end of file diff --git a/Documentation/README.md.meta b/Documentation/README.md.meta new file mode 100644 index 0000000..125a6de --- /dev/null +++ b/Documentation/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 17ed6166c017a4fcda77ff618f2703db +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Plugins.meta b/Plugins.meta new file mode 100644 index 0000000..bbcf194 --- /dev/null +++ b/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc389bcfbbddc4d35a997cbc06799975 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Plugins/TapTap.Bootstrap.deps.json b/Plugins/TapTap.Bootstrap.deps.json new file mode 100644 index 0000000..1229ab6 --- /dev/null +++ b/Plugins/TapTap.Bootstrap.deps.json @@ -0,0 +1,233 @@ +{ + "runtimeTarget": { + "name": ".NETStandard,Version=v2.0/", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETStandard,Version=v2.0": {}, + ".NETStandard,Version=v2.0/": { + "TapTap.Bootstrap/1.0.0": { + "dependencies": { + "NETStandard.Library": "2.0.3", + "TapTap.Common": "1.0.0", + "TapTap.Login": "1.0.0", + "Common": "1.0.0.0", + "LiveQuery": "1.0.0.0", + "Storage": "1.0.0.0", + "Storage.Unity": "1.0.0.0", + "UnityEngine": "0.0.0.0" + }, + "runtime": { + "TapTap.Bootstrap.dll": {} + } + }, + "Microsoft.NETCore.Platforms/1.1.0": {}, + "NETStandard.Library/2.0.3": { + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, + "TapTap.Common/1.0.0": { + "runtime": { + "TapTap.Common.dll": {} + } + }, + "TapTap.Login/1.0.0": { + "dependencies": { + "TapTap.Common": "1.0.0" + }, + "runtime": { + "TapTap.Login.dll": {} + } + }, + "Common/1.0.0.0": { + "runtime": { + "Common.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "LiveQuery/1.0.0.0": { + "runtime": { + "LiveQuery.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "Storage/1.0.0.0": { + "runtime": { + "Storage.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "Storage.Unity/1.0.0.0": { + "runtime": { + "Storage.Unity.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "UnityEngine/0.0.0.0": { + "runtime": { + "UnityEngine.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } + }, + "LC.Newtonsoft.Json/11.0.0.0": { + "runtime": { + "LC.Newtonsoft.Json.dll": { + "assemblyVersion": "11.0.0.0", + "fileVersion": "11.0.1.0" + } + } + }, + "Realtime/1.0.0.0": { + "runtime": { + "Realtime.dll": { + "assemblyVersion": "1.0.0.0", + "fileVersion": "1.0.0.0" + } + } + }, + "LC.Google.Protobuf/3.14.0.0": { + "runtime": { + "LC.Google.Protobuf.dll": { + "assemblyVersion": "3.14.0.0", + "fileVersion": "3.14.0.0" + } + } + }, + "System.Memory/4.0.1.1": { + "runtime": { + "System.Memory.dll": { + "assemblyVersion": "4.0.1.1", + "fileVersion": "4.6.27617.2" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/4.0.4.1": { + "runtime": { + "System.Runtime.CompilerServices.Unsafe.dll": { + "assemblyVersion": "4.0.4.1", + "fileVersion": "4.0.0.0" + } + } + }, + "System.Buffers/4.0.2.0": { + "runtime": { + "System.Buffers.dll": { + "assemblyVersion": "4.0.2.0", + "fileVersion": "4.6.25519.3" + } + } + }, + "System.Numerics.Vectors/4.1.3.0": { + "runtime": { + "System.Numerics.Vectors.dll": { + "assemblyVersion": "4.1.3.0", + "fileVersion": "4.6.25519.3" + } + } + } + } + }, + "libraries": { + "TapTap.Bootstrap/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Microsoft.NETCore.Platforms/1.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "path": "microsoft.netcore.platforms/1.1.0", + "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512" + }, + "NETStandard.Library/2.0.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "path": "netstandard.library/2.0.3", + "hashPath": "netstandard.library.2.0.3.nupkg.sha512" + }, + "TapTap.Common/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "TapTap.Login/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Common/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "LiveQuery/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Storage/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Storage.Unity/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "UnityEngine/0.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "LC.Newtonsoft.Json/11.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "Realtime/1.0.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "LC.Google.Protobuf/3.14.0.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Memory/4.0.1.1": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Runtime.CompilerServices.Unsafe/4.0.4.1": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Buffers/4.0.2.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + }, + "System.Numerics.Vectors/4.1.3.0": { + "type": "reference", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/Plugins/TapTap.Bootstrap.deps.json.meta b/Plugins/TapTap.Bootstrap.deps.json.meta new file mode 100644 index 0000000..92c4277 --- /dev/null +++ b/Plugins/TapTap.Bootstrap.deps.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 31cab863b627d4a509bd0f259bcf6a31 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Plugins/TapTap.Bootstrap.dll b/Plugins/TapTap.Bootstrap.dll new file mode 100644 index 0000000000000000000000000000000000000000..9e2d444f347cd9b45fc4af6c31e782d5002549cd GIT binary patch literal 28672 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 Ef0d4yC;$Ke literal 0 HcmV?d00001 diff --git a/Plugins/TapTap.Bootstrap.dll.meta b/Plugins/TapTap.Bootstrap.dll.meta new file mode 100644 index 0000000..6dcd382 --- /dev/null +++ b/Plugins/TapTap.Bootstrap.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 03acb073a9f88474581401ef1020c1c4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Plugins/TapTap.Bootstrap.pdb b/Plugins/TapTap.Bootstrap.pdb new file mode 100644 index 0000000000000000000000000000000000000000..71f924f5326888ea8e88ffb30407eba9e649bb77 GIT binary patch literal 14088 zcmaJ|2S8I-_rD1tAP}}7pb|DR!WIy%K*F8^DoPz8c|as2F$pNnAX-pVTwfLSueh}? z9JQ`mwRP03)jDbwYt>q<*3qxjI{xRr0gr%R^t|(a_nvd^x%Zws-g}qC{PaW);voF9 z0?L&n3ai3Ip=1K$qbYEs0rJX~7vr?2K;Kyco`z5hDD1^~`FgEFRjR}Jasfg-oHjHc zmBIa3e4jEjO#=Kh;P`%k6P0RgEM2Q<3dsFJa@bw}E)xCs_A~M0rI3tapgusofv^s)l^KvDje#L9l?->!F@)cD$Of+1 zb|nzjbpo;m!uC?YN*-v<1l|bzEb!~V%{d(8$l;V@!n{heFfy+hd zz=r{!2fPXRW#B&pcQWB1PZKW620jw_N#HktyYM(DkOyAUKNDmlG(kck4}}SFk||mu zG)3Ri_rJpZpF%$R8_2}N4A}q)J7KsumFKs7-1 zK#f431N|S+dZ4X9yMYb>9R)fCbOGoZ&~2dmK)(aM0BQsJ0L1qeAb~gKQTJB?a%|5R zpxz)a0*VL91Cj$(0kyWvU@NBRZxWj#a~wi|T}W<@hWVJIQS|){lH+{*vqXJ-Es?jc z00ja?0L1}`fii&deX)!H714Y)&3DuMHqH5dlw2syH8fvM^Y2Mc$qe)tpkkmc{uDNW z5rpHN2a!mPTQ|Tw7LEgK3Ybgh<8f^U{}`+VY|g^5fP1iT1Yipm76G;dY(m?E;SYVz zYsY4Q1xDDKg|UA&Ec_6#EtFtN+p_~~$HFj8z}V}Y@4&)1-;srb0rzBKJZ_y>80R~) zFwXDA!nlK7SQzKKvM~0~%?S5qVeC&I7RK{aUnA_!!gC>C$ildPJXkmyuqO+L0QO>G z-2UDyjO*tE?aQaz6Suc73+Ds&gB~)Y^Kt$BSs44@kA-ph494>yo*x6C$INN{a=<~z zp&jG-QUoo|Wjc|k!jx@qiM!3HbjyA$EMmW|84=}=UMtGnR9%O_+ zF~Wn5aJ&&tFv5vOSZstPMmWg`C$lh)mlPJp{h7+bDS*>hI0tY#3uFBZ7RLISER6HB zSQy7+HVb3>IV_Czb6FTqU_)3K$7>!7<9Nzv;humCjPOtv-U|7{09(-UnGSe3U`ra~ zJwhQ1V}C}%XkhaD1O61S6)lhPXutv*p8-4;tTWgHu#|-xVH##I9{Xv4Wsq+}>pQYA zo=dI)mBM(krStK4DKo+fNMrKx{5p<>&EX!8L3X~9g>ilb3uAp13*&qZvidVvG6Xy6Ir+k@FW&?g8DNU*Z(@u6v%g=?JovAjfGnP8(4S< zY=;=^0(o!2UM=MJr1j$=Z6;u68qWkg3$QDVD?pyXcrVx&a2@3Lq4T#v8vaoWy+ivw z2UZ3Aqw;Ys2Mr`s@J^9Kr&GB}WIAp=6Np8;9w)$+i;7uSC>C<5lt}U(_X>`EYz@!i z%snMj3Yd##!_@>Whbs?S0slD2QV2}~srY`T&=fe1Ar9IA`#HRp7U<9E}nTP!&Z04(>nZ%<(MW4Of1RSvqJ^>Z1>l1KcZ0b}gJ4W(OuDi62ovAp9x&;WEwP%@arW zGp!E%{W-_*+351%*QvuE5x*=N8#mU&8q`yy6-2(Yis7n79(9} z>MaT+`FId@D!f)KB+gmn{?eRW|6$Ue(@!4C3+_J9HWz;5{p4yv@`E3OUP?@0CNj$- zl!R1ASgQyaSuh7lweoOLXox5~sQ_w4;-FzLKw;V$R0TPr1f7nkC{|V{=;7r_aiyNn zLAiGApc6x1H?dL-Mx+0N@?K4G?I40lq{oQ-DRj;##KWU3BdGv6@e(PXIcc?de zJhvN8QFoh+>wP&-4(-sf*TZy|Q5Q^QSX}Rg|YF z98aYhm^-z>Oj3j>3|hOwSHPSt zsa8oV6f&4@t1}gJL3v4;NeTH$LAa|660#);c@p-0_?S>O3>yuAM;HaAD&&5voF&GXewEh#HL^u70FW<+a+PNvo> z6~(mJb1Vkin*L3eapse?Su00OiN5S{au#b)(vqKBgJirT5?$F|v6OQm(eTCd=S{PU zTJ!bfL_|xSb!qqv9p$2!#+zcn_rt`qkJRno9Fy^iks6BERa$nMZ_9Vs#j~=_e=SEl z;6dTxl6jy&DRhzg;c4SM97Vl1AcJoJGR9? zVZ-4cg~R4~7}}L9G_Ye)>9f>wLJ1WGsDqwYt7v_u<8SQU@;p~LGjsDXr|%~2x@X?K ze&@=Dc-_c*h+;CgZi_v5czD&o?sbx?p!h_Xy5$MFY86xIV|4E{Kb?7Vh3}F0#l8ct zIyWiib#J3fyfW$={KvYr*vt^GJjWkABE096?$rybH3alA%&>Y`eW*$>7TzBH{Zx!| zZE8*5hrWdOC;QqhsB~&2VI=&URqEA|C5N*1-O@dHPmHi@7uGV82k3g8{%qWW;#10m z?HdCY?pbuGnU=&GYupR4p)oSOrGEC~Gh-983@t(SmuA>7jY%p{9y6w6BS*bTUA$TH z<=ta%Hu>j>8Pf`BsYTbwVf|02E8y&JV;SZL_wms}Sqml*?fHvh4Y6)nwN^s>*`W6^n| zyD^ZfRm&P7S-APcGGTnWyL`cfB|(DRj=2%-wIbA^cSvw|ztzz6u#B zmR@tO+P>LdT$46(UCY+^8?++TAJ4FLSVx|O=4QwqK9+1=JMh(s-;Ru9tZStcIxI3% z!=PLL5kLK+SzPyRBIjX|Q>l?~m$AuI;hc@zll^CG()RkzwR4Nu|B}(8HXfopYTsbw ze(JJA^J9IsWiNfPZ|dsh&NFGH6!@Tp=RI;)A`(lL@YpHUGA+)OIM0=LEyYfqxwEXy z|9y1EfNqtkmS9wRhaVp*jhUXh=H>grZ%4X4?p7sfB7_CrSsE9Zcv!_>KSC;AKSyG5 z=9+yit(}%b&b07witm)9D%3xgddn|CUEI*vH zc6v|V^PT=oqd>K~xOJAURSQ?;FS{d2YAk#_V5#~LGevY(k!WGd!I~Zz-{xCgjo0JX9VO-}H0{zC=yH~P+Q8X%qgk?3 z9+dLq*HUJ$1LX`=!HXE!>&vME;R7)tt)OeiXg3(rH=ExcoW68@xa)(~?M=aivv~k$DX=AJQr?FMYjjXh|J!&t}jnKRC)$2!h&Zm7bZIolk zZaK3F%O;qe-V<8TbNFtP>4hiL53gvlXfbU1oHmXHQ}ucc?aF0Z`XTSbO8)k{33Z&r z*2Nohud$@F;dwugfC#8$?UWcjQ^{-lvq{Z4tM>f7?5nuXlGu8Leu7$Cjw4)KK}}Uu z^%>owjja_QnuFpO5BDE4=EIVFmTqpx#LGw@e5riK-}x$i&SA6V2Xiv+vZakT@K@+s zEnFSayQz*y|LW}cumT@z9ZQFPb;k4}qv8Ch;V5_C((Hr0yY*h#nU`4_`2=i>J9gkd z&}EFg)RwY~uSs9~U&WZUp1dZuhFVq*59oALU!@fis?W@Ebj=g5uy_(s68!2jmcnqN zIF*pXTaAwWxRJ7Z>W(zqSd*+dXTukc2>Gq1vvNLNpjZiSBAI|-%Kb)L_?y}5=A;#4 z_RahI|4PqvuS#{%HQLwn370SJdABchz17pkuXlUeGdh(Oc+1Yzj0w3fIIXV_ZM>Z_ zN8fs^?%xGwv~&*n>Xh1ZcQ)Vq)PGi8tGb=GbzfrsiZj>CX@xwZgnk;KYtOhN$h$ZF zk6(r+eUS88iMtzfoR2^j(;np}F0vV+ojD0% z7o|eU!Y2|F#oHq0iIOR@ONZQ|T`fvC>zjA_Vag8motSqelHo>$q{3UQjs=5JY8aLB zuXV4s#DzNH;Uj|%&oxp?gGXMiTGL)VD%u!jnX+fghFh-^=cxC2M#l=6)rRrZSeZ`m zI)D8{*P!6uknb*ERAn4!au?1s3wUbeOm^o%!f3Vn_Pg`qgLCQ*ulJiy-o3;u(2N)0 zJNZn@o-m)$1)d#zj{iclCUbTD{bbL8seOzJ?5vth&brVZ%qYE0TlqHY*L~^b4cQCC zCoU&U8o_K%x_2O5*S=+A^d+OOaBTibPMQeYpQC2NVP?oA;x-aWuCI7Q8cF4s3;!Unmj~?mc zJ^!Z_v5r}3@6t~EGVJh`*>m4!tr(covxJw#Jlb}6&UPY6B~!~g)#9PHZGjUinL;CF`td%kx2KudqF&;cIQ#0>8BTEn zy7VL2EbyitpZKGTWK>VTp7nn8wI>NpV`g9ceuCBe_9Dr-jaqJCL8Y~rF=TsBw?JT; zne|Owp=8R;247kWKl_S|TAL~8UCAqlW!ANl84J$N+PG#h^XS@HrOQ0WXusX|df>Wd zWyaFG5w}YVw=pe4YUdH9l}f3$>!y-Xu59{oarvw#$@O_f8yqH{o6mS#1{+*fT>Q%P zsC@SZ(^JLS|Cw`Qy7QnKW<4!v7tevWK1y;sPB#mqX&-R&op|nt%*E?3zW%f5>EaYwEKNTYad(ZFI{-{P5kDO`?U3s zeVFGQmNw}&?I=^`r*q88_KrM~vMb}>z!I+;9$g(JwQ}JVgpsBwWI>;$KhU?#x6ynQ@#rN}#L zb?P6f*HfRl(Hg^~%1WZ3Qq#VnXG%CTviwTJ!ue^-7eBMxkT9KjOz#@G_jZ?k6&)l_ z*jsvM-mDFS_R@yo9kyIOf$19Zoiw}`Ru_hx+a8pbv1+{B;i2P)OSEvuL`n+6^4(Nx z`MH%#QOZ|wna||U^-P3eLDr+u3%bvA%M^CYcSnntRn124wqId3;aHm51a;b#Fjdrl zzpZH9Lc8qcCSl{J-o56-a;Ec|Ma?NpVcTr2+j5-VWi?8#Zt~jo`WQ>CP@^4h+~ z{hju2^_%pfz+3N9*Yg%y`cHn=%2ugR8YwZ`)`DxtQl|vxWGqP8zUtD&6;Yj)7!TV+ zgHhWttg^gjPPt^p>XSC7zdRkuR?C&@%joc9#M55Bnb!Z?gE>3D+0kPmZ;fpiapO8M zik}@Fo{?9(HQr##@4NRwv4Hyc*!jKbsK%3R_*It6TJz&3A>XIYP_(_?zHMayElYl> zr2Tp1q=OSS928vvk&*Q%Wt;cElE)4AOUbVbNhW5WqcDm%L}yKNb$j^mY`$u~(is2leJx!*NKs;~VCi zSC2=b)}ZaggEL=dNW|d<@$v_wNSp?y_*7Fcdy|d_L7j;HP|}xfEOr*_5vvECot9(I zSu>KeM#@<;g|lV_)l#?~PWFzNIXaNcr5DMZT^#w4n%b8{uI?m@_ok2!$p#0ItWO}x zoI|O+D3Uo2AlZPyBpW1gOoS5L(*$rX8pT^8Pi}$$g`s3iw#WwVd6i~x?`@bfzzsUb*{~Q|-I)sq=v?u| zg9}IH1h`kBbBuz}6oN1Xg<8>Vi(7+=RyPaiEg=pRIymj@1P}la7I3JF@8oHP&qA3a zg*kHMO@On^Q+tCu)`(+1v`2eT_Ta4jmx?}oq$$@@&YsNl}>wsIhufMRwOv!|F7#hfYTMlpAac|lWw zx*x>?DHcMp2#Q5hERJG>DJG^^3dJ%gmP4_8iVdgOrxY72zgH5VW!eCNc4@eW<=frloU(hH~f^2b}@ zSaO0M^{VlQ_#FUdOrQ>-2;8@Y^Og~Dc8*{ij|W-V}%2bFZkH=p4!+@m0_;4(Aqy_RZ)ZnrUphU84Z%Y)&9R=t3h8h{c z$8*zxWb5E^2;bm{6Ik`f%ubMm!-8k{nc?Xaz9XS|8pZF@_->jz{+k#`G(rC5*n=Us z>tNV3p5x==aGo5Ycp!}{{tFyZI=K=@9vp`3B#4hW;`Y_LwF~Az%>Won#)4EXkiJ8* z*w83|KQ%Fy#0PvK4OMkWMjDpF+SWzV52QW;n&{sbuHdExN;0e#Kr0S|z=9L0aPYWu z?VLakMFC+~CgG#9`|yp>9j;_G?G2j+rZ@tixNI_z$o?c-B?yGXKvUd=a3!N~fZ>n; zLbA}PS@5~i0-$N1c)%45+oN8F;}GHQX_iBix&74gmnCXt{h0CW9H?_ylh# z8(IQ_F&GJJBB>?WloM}W?ZlDrpdtA@IFTA=j)jUW;ZLD@JMenJ-&5c!`s0xT>F|;Z z=nRly7No#&XQ)|#58OZ|{JB(32{y|$=OTaXJ)B#0BSRKOIoUa+2^e3 C)RE!< literal 0 HcmV?d00001 diff --git a/Plugins/TapTap.Bootstrap.pdb.meta b/Plugins/TapTap.Bootstrap.pdb.meta new file mode 100644 index 0000000..1456e1e --- /dev/null +++ b/Plugins/TapTap.Bootstrap.pdb.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b3d6c5154fb9d4319a2a32e6fde07f63 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac2eea9 --- /dev/null +++ b/README.md @@ -0,0 +1,254 @@ +# [使用 TapTap.Bootstrap ](./Documentation/README.md) + +## 使用前提 + +使用 TapTap.Bootstrap 前提是必须依赖以下库: +* [TapTap.Common](https://github.com/TapTap/TapCommon-Unity.git) +* [TapTap.Login](https://github.com/TapTap/TapLogin-Unity.git) +* [LeanCloud.Storage](https://github.com/leancloud/csharp-sdk) +* [LeanCloud.RealTime](https://github.com/leancloud/csharp-sdk) + +## 命名空间 + +```c# +using TapTap.Bootstrap; +``` + +## 接口描述 + +## 1.初始化 + +TapBootstrap 会根据 TapConfig 中的 TapDBConfig 配置来进行 TapDB 的自动初始化。 + +### 开启 TapDB +```c# +var config = new TapConfig.Builder() + .ClientID("client_id") + .ClientToken("client_token") + .ServerURL("https://ikggdre2.lc-cn-n1-shared.com") + .RegionType(RegionType.CN) + .TapDBConfig(true,"channel","gameVersion",true) + .Builder(); +``` +### 关闭 TapDB +```c# +var config = new TapConfig.Builder() + .ClientID("client_id") + .ClientToken("client_token") + .ServerURL("https://ikggdre2.lc-cn-n1-shared.com") + .RegionType(RegionType.CN) +//# .TapDBConfig(false,null,null,false) + .EnableTapDB(false) + .Builder(); +``` +### 初始化 +```c# +TapBootstrap.Init(config); +``` + +## 2.账户系统 + +> 登陆成功之后,都会得到一个 `TDSUser` 实例 + +### 使用 TapTap OAuth 授权结果直接登陆/注册账户系统 + +```c# +var tdsUser = await TDSUser.LoginWithTapTap(); +``` + +### 游客登陆 + +```c# +var tdsUser = await TDSUser.LoginAnonymously(); +``` + +### 使用第三方平台授权登录/注册账户 + +```c# +var tdsUser = await TDSUser.LoginWithAuthData(Dictionary authData, string platform, +LCUserAuthDataLoginOption option = null); +``` + +### 绑定第三方平台授权 + +```c# +await TDSUser.AssociateAuthData(Dictionary authData, string platform); +``` + +### 退出登陆 + +```c# +TDSUser.Logout(); +``` + +## 3.好友系统 + +### 申请成为好友 + +```c# +TDSUser tom, jerry; +await tom.ApplyFriendship(jerry); +``` +申请成功的回调中,我们会得到一个 LCFriendshipRequest 的实例,这个实例中包含了两个用户: +- sourceUser,指请求的发起方,上面的例子中就是 `tom`。 +- friend,指请求的目的方,上面的例子中就是 `jerry`。 + +tom 也可以在申请好友的时候,添加更多的属性,例如 tom 希望加 jerry 为好友的时候,也设定一个名为 cat 的圈子,可以这样操作: + +```cs +Dictionary attrs = new Dictionary { + { "group", "cat" } +}; +await tom.ApplyFriendship(jerry, attrs); +``` + +### 获取好友申请列表 +好友申请有三种状态: + +- `pending`,对方没有回应,还处于等待中。 +- `accepted`,对方已经接受,现在双方成为好友。 +- `declined`,对方已经拒绝。 + +好友请求创建之后默认是 `pending` 状态。 + +jerry 这里可以通过 `friendshipRequestQuery` 来查找不同状态的请求。例如 jerry 想看看新的好友请求,可以这样操作: + +```cs +LCQuery query = jerry.GetFriendshipRequestQuery(LCFriendshipRequest.STATUS_PENDING, false, true); +ReadOnlyCollection reqs = await query.Find(); +foreach (LCFriendshipRequest req in reqs) { + Console.WriteLine(req); +} +``` + +### 处理好友申请 + +jerry 对于新的好友请求,可以同意或者拒绝,也可以什么都不做,无视这些请求,甚至直接删除。这些操作我们都是支持的,请看下面的示例: + +```cs +LCFriendshipRequest tomRequest, tuffyRequest, otherRequest; +await jerry.AcceptFriendshipRequest(tomRequest); +await jerry.DeclineFriendshipRequest(tuffyRequest); +await jerry.DeleteFriendshipRequest(otherRequest); +``` + +注意: +* 在 jerry 拒绝了 tom 的好友请求之后,如果 tom 再次请求成为 jerry 的好友,tom 在执行 applyFriendshipInBackground 时会直接得到错误的应答,表明 jerry 不想和 ta 成为好友。 +* jerry 同意了 tuffy 的好友请求之后,它们就成为了好友,之后两个人中任何一人再次调用 applyFriendshipInBackground 申请横位好友时,也会直接得到错误的应答,表明它们已经是好友无需再次申请。 +* jerry 删除陌生人的好友请求后,对方还可以再次发起请求。 + +### 响应好友变化通知 + +TDS 好友模块支持客户端监听好友状态变化,在游戏中实时给玩家提示。好友状态变化的接口包括 + +```cs +public class FriendshipNotification { + public Action OnNewRequestComing { get; set; } + public Action OnRequestAccepted { get; set; } + public Action OnRequestDeclined { get; set; } +} +``` + +其中: +- onNewRequestComing 表示有其他人申请成为当前用户的好友,通过调用 `LCFriendshipRequest#getSourceUser()` 方法可以获得发起方用户信息。 +- onRequestAccepted 表示当前用户的好友申请被对方通过,通过调用 `LCFriendshipRequest#getFriend()` 方法可以获得对方用户信息。 +- onRequestDeclined 表示当前用户的好友申请被对方拒绝,通过调用 `LCFriendshipRequest#getFriend()` 方法可以获得对方用户信息。 + +开发者可以通过 `TDSUser#registerFriendshipNotification` 来注册通知接收器,通过调用 `TDSUser#unregisterFriendshipNotification` 来取消通知接收器。 + +### 获取好友列表 + +调用 `TDSUser#friendshipQuery()` 可以得到查询好友的 `LCQuery` 实例,之后调用 `LCQuery#findInBackground()` 方法就可以得到好友列表。示例如下: + +```cs +LCQuery query = jerry.GetFirendshipQuery(); +``` + +LCFriendship 里面会包含两个用户: + +- `LCFriendship#getLCUser(LCFriendship.ATTR_USER)` 得到的是 jerry 自己; +- `LCFriendship#getLCUser(LCFriendship.ATTR_FOLLOWEE)` 得到的就是另一方的用户信息。 + +### 删除好友 + +成为好友关系的两个用户,之后也可以单方面删除好友。例如 jerry 不想再和 tom 成为好友,那只需要在自己的好友列表中删除包含 tom 的那条 LCFriendship 记录即可: + +```cs +await friendship.Delete(); +``` + +### 查询好友关系 + +我们使用 LCQuery 可以单独查询两个用户是否为好友关系。 + +```cs +LCQuery query = jerry.GetFirendshipQuery(); +query.whereEqualTo("followee", tom); +int count = await query.Count(); +if (count > 0) { + // tom is a friend of jerry. +} else { + // tom isn't a friend of jerry. +} +``` + +这一查询是通过网络发送到服务端执行的,一般情况下,我们推荐开发者在游戏启动时拉取一次当前登录用户的好友列表,然后缓存在本地,以后需要检查另外玩家是否为当前用户的好友时,直接从缓存中查询即可。如果担心好友数据变化,缓存没有得到及时更新,可以调用前面「响应好友变化通知」的方法,对好友数据更新进行监听,这样在绝大部分时候数据同步都是可以保证的。 + +## 4.云存档 + +### 构建云存档元数据 + +```c# +var gameSave = new TapGameSave +{ + Name = "GameSave_Name",// 存档名称 + Summary = "GameSave_Description", // 该字段会作为展示给用户的实际存档名 + ModifiedAt = DateTime.Now.ToLocalTime(), // 原文件修改时间 + PlayedTime = 1000L, // 游戏时长,单位 ms (非必填) + ProgressValue = 100, // 游戏进度 ,单位 int (非必填) + CoverFilePath = pic, // 游戏封面,可以传入一个本地文件路径,SDK 限制为 png/jpeg 格式 + GameFilePath = dll // 存档源文件,可以传入一个本地文件路径 +}; + +``` +### 保存存档 + +保存存档时,会去检查当前`TDSUser`是否已经登录以及元数据。 + +同时 SDK 在上传时会去限制存档本身以及相关联的两个文件( Cover 以及 GameFile )的权限为当前用户本身。 +```c# +await gameSave.Save(); +``` + +### 查询当前用户的所有存档 + +```c# +var collection = await TapGameSave.GetCurrentUserGameSaves(); + +foreach(var gameSave in collection){ + // 存档概览 + var name = gameSave.Summary; + // 原文件修改时间 + var modifiedAt = gameSave.ModifiedAt; + // 游戏时长 + var playedTime = gameSave.PlayedTime; + // 游戏进度 + var progressValue = gameSave.ProgressValue; + // 游戏封面 + var coverFile = gameSave.CoverFile; + // 存档源文件 + var gameFile = gameSave.GameFile; + // 源文件下载地址 + var gameFileUrl = gameFile.Url; +} +``` + +### 查询云存档 +云存档只能查询当前用户的所有存档,需要查询该用户的特定存档时,可以增加相应过滤,可参考 [查询条件](https://developer.taptap.com/docs/sdk/storage/guide/objc/#%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6) +```c# +TDSUser user = await TDSUser.GetCurrent(); +LCQuery gameSaveQuery = TapGameSave.GetQueryWithUser(user); +// 查询 Name 为 TDSUser_GameSave_Name 的云存档 +gameSaveQuery.WhereEqualTo("name","TDSUser_GameSave_Name"); +var collection = await gameSaveQuery.Find(); +``` diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..74191cc --- /dev/null +++ b/README.md.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c5330aab2c6a41699a1601f1af6b27d9 +timeCreated: 1616755935 \ No newline at end of file diff --git a/VERSIONNOTE.md b/VERSIONNOTE.md new file mode 100644 index 0000000..78f4676 --- /dev/null +++ b/VERSIONNOTE.md @@ -0,0 +1,6 @@ +### Dependencies + +- TapTap.Login v3.5.0 +- TapTap.Common v3.5.0 +- LeanCloud.Realtime v0.10.0 +- LeanCloud.Storage v0.10.0 \ No newline at end of file diff --git a/VERSIONNOTE.md.meta b/VERSIONNOTE.md.meta new file mode 100644 index 0000000..4bb7039 --- /dev/null +++ b/VERSIONNOTE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d5391b17003874fb2afc3e309a3f63ef +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json new file mode 100644 index 0000000..cb25b99 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "com.taptap.tds.bootstrap", + "displayName": "TapTap Bootstrap", + "description": "TapTap Develop Service", + "version": "3.5.0", + "unity": "2018.3", + "license": "MIT", + "dependencies": { + "com.taptap.tds.common": "https://github.com/TapTap/TapCommon-Unity.git#3.5.0", + "com.taptap.tds.login": "https://github.com/TapTap/TapLogin-Unity.git#3.5.0", + "com.leancloud.realtime": "https://github.com/leancloud/csharp-sdk-upm.git#realtime-0.10.0", + "com.leancloud.storage": "https://github.com/leancloud/csharp-sdk-upm.git#storage-0.10.0" + } +} diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..a42bf59 --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e618b9375caf846708cffea428908521 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: