| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using System.Threading.Tasks;
- using Newtonsoft.Json;
- using TapSDK.CloudSave.Internal;
- using TapSDK.Core;
- using TapSDK.Core.Internal.Log;
- using TapSDK.Core.Internal.Utils;
- using TapSDK.Core.Standalone;
- using TapSDK.Core.Standalone.Internal;
- using TapSDK.Core.Standalone.Internal.Http;
- using TapSDK.Login;
- using UnityEngine;
- namespace TapSDK.CloudSave.Standalone
- {
- public class TapCloudSaveStandalone : ITapCloudSaveBridge
- {
- private List<ITapCloudSaveCallback> currentSaveCallback = null;
- private static readonly bool isRND = false;
- private bool _hasInitNative = false;
- private object _lockObj = new object();
- private TapLog cloudSaveLog;
- public void Init(TapTapSdkOptions options)
- {
- Log("TapCloudSave start init");
- TapCloudSaveTracker.Instance.TrackInit();
- string cacheDir = Path.Combine(
- Application.persistentDataPath,
- "cloudsave_" + options.clientId
- );
- string deviceID = SystemInfo.deviceUniqueIdentifier;
- Task.Run(async () =>
- {
- TapTapAccount tapAccount = await TapTapLogin.Instance.GetCurrentTapAccount();
- string loginKid = "";
- string loginKey = "";
- if (tapAccount != null && !string.IsNullOrEmpty(tapAccount.openId))
- {
- loginKey = tapAccount.accessToken.macKey;
- loginKid = tapAccount.accessToken.kid;
- }
- Dictionary<string, object> loginData = new Dictionary<string, object>
- {
- { "kid", loginKid },
- { "key", loginKey },
- };
- int region = isRND ? 2 : 0;
- try
- {
- Dictionary<string, object> initConfig = new Dictionary<string, object>()
- {
- { "region", region },
- { "log_to_console", 1 },
- { "log_level", 3 },
- { "data_dir", cacheDir },
- { "client_id", options.clientId },
- { "client_token", options.clientToken },
- { "ua", TapHttpUtils.GenerateUserAgent() },
- { "lang", Tracker.getServerLanguage() },
- { "platform", "PC" },
- { "device_id", deviceID },
- { "sdk_artifact", "Unity" },
- { "sdk_module_ver", TapTapCloudSave.Version },
- { "sdk_token", loginData },
- };
- Log(" start invoke TapSdkCloudSaveInitialize result ");
- string config = JsonConvert.SerializeObject(initConfig);
- int initResult = TapCloudSaveWrapper.TapSdkCloudSaveInitialize(config);
- Log("TapSdkCloudSaveInitialize result = " + initResult);
- if (initResult < 0)
- {
- RunOnMainThread(() =>
- {
- if (currentSaveCallback != null && currentSaveCallback.Count > 0)
- {
- foreach (var callback in currentSaveCallback)
- {
- callback?.OnResult(TapCloudSaveResultCode.INIT_FAIL);
- }
- }
- });
- }
- else
- {
- lock (_lockObj)
- {
- _hasInitNative = true;
- }
- }
- }
- catch (Exception e)
- {
- Log("TapSdkCloudSaveInitialize error " + e.Message);
- }
- });
- EventManager.AddListener(EventManager.OnTapUserChanged, OnLoginInfoChanged);
- }
- public Task<ArchiveData> CreateArchive(
- ArchiveMetadata metadata,
- string archiveFilePath,
- string archiveCoverPath
- )
- {
- var taskSource = new TaskCompletionSource<ArchiveData>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "createArchive";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- byte[] fileBytes = File.ReadAllBytes(archiveFilePath);
- byte[] coverData = null;
- if (!string.IsNullOrEmpty(archiveCoverPath))
- {
- coverData = File.ReadAllBytes(archiveCoverPath);
- }
- string metaValue = JsonConvert.SerializeObject(metadata);
- string result = TapCloudSaveWrapper.CreateArchive(
- metaValue,
- fileBytes,
- fileBytes.Length,
- coverData,
- coverData?.Length ?? 0
- );
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(result);
- if (response.success)
- {
- ArchiveData data = response.data.ToObject<ArchiveData>();
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- var archiveData = new ArchiveData()
- {
- FileId = data.FileId,
- Uuid = data.Uuid,
- Name = metadata.Name,
- Summary = metadata.Summary,
- Extra = metadata.Extra,
- Playtime = metadata.Playtime,
- };
- taskSource.TrySetResult(archiveData);
- }
- else
- {
- try
- {
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "createArchive failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"创建存档失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "创建存档失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "创建存档失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"创建存档失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- public Task<ArchiveData> DeleteArchive(string archiveUuid)
- {
- var taskSource = new TaskCompletionSource<ArchiveData>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "deleteArchive";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- string result = TapCloudSaveWrapper.DeleteArchive(archiveUuid);
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(result);
- if (response.success)
- {
- ArchiveData archiveData = response.data.ToObject<ArchiveData>();
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- taskSource.TrySetResult(archiveData);
- }
- else
- {
- try
- {
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "deleteArchive failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"删除存档失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "删除存档失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "删除存档失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"删除失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- public Task<byte[]> GetArchiveCover(
- string archiveUuid,
- string archiveFileId
- )
- {
- var taskSource = new TaskCompletionSource<byte[]>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "getArchiveCover";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- byte[] result = TapCloudSaveWrapper.GetArchiveCover(
- archiveUuid,
- archiveFileId,
- out int coverSize
- );
- if (coverSize >= 0)
- {
- taskSource.TrySetResult(result);
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- }
- else
- {
- try
- {
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(
- Encoding.UTF8.GetString(result)
- );
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "getArchiveCover failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"获取封面失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "获取封面失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "获取封面失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"获取封面失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- public Task<byte[]> GetArchiveData(
- string archiveUuid,
- string archiveFileId
- )
- {
- var taskSource = new TaskCompletionSource<byte[]>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "getArchiveData";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- byte[] result = TapCloudSaveWrapper.GetArchiveData(
- archiveUuid,
- archiveFileId,
- out int fileSize
- );
- if (fileSize >= 0)
- {
- taskSource.TrySetResult(result);
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- }
- else
- {
- try
- {
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(
- Encoding.UTF8.GetString(result)
- );
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "getArchiveData failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"获取存档失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "获取存档失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "获取存档失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"获取存档失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- public Task<List<ArchiveData>> GetArchiveList()
- {
- var taskSource = new TaskCompletionSource<List<ArchiveData>>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "getArchiveList";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- string result = TapCloudSaveWrapper.GetArchiveList();
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(result);
- if (response.success)
- {
- TapCloudSaveArchiveListResponse archiveDatas =
- response.data.ToObject<TapCloudSaveArchiveListResponse>();
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- taskSource.TrySetResult(archiveDatas.saves);
- }
- else
- {
- try
- {
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "getArchiveList failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"获取存档列表失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "获取存档列表失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "获取存档列表失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"获取存档列表失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- public void RegisterCloudSaveCallback(ITapCloudSaveCallback callback)
- {
- currentSaveCallback?.Clear();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "registerCloudSaveCallback";
- TapCloudSaveTracker.Instance.TrackStart(method, seesionId);
- if (currentSaveCallback == null)
- {
- currentSaveCallback = new List<ITapCloudSaveCallback>();
- }
- if (!currentSaveCallback.Contains(callback))
- {
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- currentSaveCallback.Add(callback);
- }
- else
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- errorMessage: "callback has already registered"
- );
- }
- }
- public Task<ArchiveData> UpdateArchive(
- string archiveUuid,
- ArchiveMetadata metadata,
- string archiveFilePath,
- string archiveCoverPath
- )
- {
- var taskSource = new TaskCompletionSource<ArchiveData>();
- CheckPCLaunchState();
- string seesionId = Guid.NewGuid().ToString();
- const string method = "updateArchive";
- Task.Run(async () =>
- {
- bool hasInit = await CheckInitAndLoginState(method, seesionId);
- if (!hasInit)
- {
- taskSource.TrySetException(new TapException(-1, "Init or login state check failed"));
- return;
- }
- try
- {
- byte[] fileBytes = File.ReadAllBytes(archiveFilePath);
- byte[] coverData = null;
- if (!string.IsNullOrEmpty(archiveCoverPath))
- {
- coverData = File.ReadAllBytes(archiveCoverPath);
- }
- string metaValue = JsonConvert.SerializeObject(metadata);
- string result = TapCloudSaveWrapper.UpdateArchive(
- archiveUuid,
- metaValue,
- fileBytes,
- fileBytes.Length,
- coverData,
- coverData?.Length ?? 0
- );
- TapCloudSaveBaseResponse response =
- JsonConvert.DeserializeObject<TapCloudSaveBaseResponse>(result);
- if (response.success)
- {
- ArchiveData data = response.data.ToObject<ArchiveData>();
- TapCloudSaveTracker.Instance.TrackSuccess(method, seesionId);
- taskSource.TrySetResult(data);
- }
- else
- {
- try
- {
- TapCloudSaveError error = response.data.ToObject<TapCloudSaveError>();
- Log(
- "updateArchive failed error = " + JsonConvert.SerializeObject(error)
- );
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- error.code,
- error.msg ?? ""
- );
- taskSource.TrySetException(new TapException(error.code, $"更新存档失败: {error.msg}"));
- }
- catch (Exception e)
- {
- TapCloudSaveTracker.Instance.TrackFailure(
- method,
- seesionId,
- -1,
- "更新存档失败: 数据解析异常"
- );
- taskSource.TrySetException(new TapException(-1, "更新存档失败: 数据解析异常"));
- }
- }
- }
- catch (Exception e)
- {
- string msg = $"更新存档失败: {e.Message}";
- TapCloudSaveTracker.Instance.TrackFailure(method, seesionId, -1, msg);
- taskSource.TrySetException(new TapException(-1, msg));
- }
- });
- return taskSource.Task;
- }
- private async Task<bool> CheckInitAndLoginState(string method, string sessionId)
- {
- if (TapCoreStandalone.CheckInitState())
- {
- lock (_lockObj)
- {
- if (!_hasInitNative)
- {
- Log("not init success, so return", true);
- return false;
- }
- }
- TapCloudSaveTracker.Instance.TrackStart(method, sessionId);
- TapTapAccount tapAccount = await TapTapLogin.Instance.GetCurrentTapAccount();
- if (tapAccount != null && !string.IsNullOrEmpty(tapAccount.openId))
- {
- return true;
- }
- else
- {
- if (currentSaveCallback != null && currentSaveCallback.Count > 0)
- {
- foreach (var callback in currentSaveCallback)
- {
- callback?.OnResult(TapCloudSaveResultCode.NEED_LOGIN);
- }
- }
- TapCloudSaveTracker.Instance.TrackFailure(method, sessionId, -1, "not login");
- return false;
- }
- }
- return false;
- }
- /// <summary>
- /// 检查是否通过 PC 启动校验
- /// </summary>
- private void CheckPCLaunchState()
- {
- #if UNITY_STANDALONE_WIN
- if (!TapClientStandalone.isPassedInLaunchedFromTapTapPCCheck())
- {
- throw new Exception("TapCloudSave method must be invoked after isLaunchedFromTapTapPC succeed");
- }
- #endif
- }
- internal void OnLoginInfoChanged(object data)
- {
- lock (_lockObj)
- {
- if (_hasInitNative)
- {
- Task.Run(async () =>
- {
- TapTapAccount tapAccount =
- await TapTapLogin.Instance.GetCurrentTapAccount();
- string loginKid = "";
- string loginKey = "";
- if (tapAccount != null && !string.IsNullOrEmpty(tapAccount.openId))
- {
- loginKey = tapAccount.accessToken.macKey;
- loginKid = tapAccount.accessToken.kid;
- }
- Dictionary<string, object> loginData = new Dictionary<string, object>
- {
- { "kid", loginKid },
- { "key", loginKey },
- };
- int result = TapCloudSaveWrapper.TapSdkCloudSaveUpdateAccessToken(
- JsonConvert.SerializeObject(loginData)
- );
- Log("update login msg result = " + result);
- });
- }
- }
- }
- private void RunOnMainThread(Action action)
- {
- TapLoom.QueueOnMainThread(action);
- }
- private void Log(string msg, bool isError = false)
- {
- if (cloudSaveLog == null)
- {
- cloudSaveLog = new TapLog("TapCloudSave");
- }
- if (!string.IsNullOrEmpty(msg))
- {
- if (isError)
- {
- cloudSaveLog.Error(msg);
- }
- else
- {
- cloudSaveLog.Log(msg);
- }
- }
- }
- }
- }
|