using UnityEngine;
using System.Threading.Tasks;
using TapSDK.Core.Internal.Utils;
using TapSDK.Core.Standalone.Internal;
using TapSDK.UI;
using System;
using System.Runtime.InteropServices;
using TapSDK.Core.Standalone.Internal.Openlog;
using System.Threading;
using TapSDK.Core.Internal.Log;
namespace TapSDK.Core.Standalone
{
#if UNITY_STANDALONE_WIN
public class TapClientStandalone
{
// 是否是渠道服游戏包
private static bool isChannelPackage = false;
// -1 未执行 0 失败 1 成功
private static int lastIsLaunchedFromTapTapPCResult = -1;
private static bool isRuningIsLaunchedFromTapTapPC = false;
// 当为渠道游戏包时,与启动器的初始化校验结果
private static TapInitResult tapInitResult;
//
// 校验游戏是否通过启动器唤起,建立与启动器通讯
//
public static async Task IsLaunchedFromTapTapPC()
{
// 正在执行中
if (isRuningIsLaunchedFromTapTapPC)
{
UIManager.Instance.OpenToast("IsLaunchedFromTapTapPC 正在执行,请勿重复调用", UIManager.GeneralToastLevel.Error);
TapLog.Error("IsLaunchedFromTapTapPC 正在执行,请勿重复调用");
return false;
}
// 多次执行时返回上一次结果
if (lastIsLaunchedFromTapTapPCResult != -1)
{
TapLog.Log("IsLaunchedFromTapTapPC duplicate invoke return " + lastIsLaunchedFromTapTapPCResult);
return lastIsLaunchedFromTapTapPCResult > 0;
}
isChannelPackage = true;
TapTapSdkOptions coreOptions = TapCoreStandalone.coreOptions;
if (coreOptions == null)
{
UIManager.Instance.OpenToast("IsLaunchedFromTapTapPC 调用必须在初始化之后", UIManager.GeneralToastLevel.Error);
TapLog.Error("IsLaunchedFromTapTapPC 调用必须在初始化之后");
return false;
}
string clientId = coreOptions.clientId;
string pubKey = coreOptions.clientPublicKey;
if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(pubKey))
{
UIManager.Instance.OpenToast("clientId 及 TapPubKey 参数都不能为空, clientId =" + clientId + ", TapPubKey = " + pubKey, UIManager.GeneralToastLevel.Error);
TapLog.Error("clientId 或 TapPubKey 无效, clientId = " + clientId + ", TapPubKey = " + pubKey);
return false;
}
isRuningIsLaunchedFromTapTapPC = true;
string sessionId = Guid.NewGuid().ToString();
TapCoreTracker.Instance.TrackStart(TapCoreTracker.METHOD_LAUNCHER, sessionId);
try
{
TapInitResult result = await RunClientBridgeMethod(clientId, pubKey);
TapLog.Log("check startupWithClientBridge finished thread = " + Thread.CurrentThread.ManagedThreadId);
isRuningIsLaunchedFromTapTapPC = false;
if (result.needQuitGame)
{
lastIsLaunchedFromTapTapPCResult = 0;
TapCoreTracker.Instance.TrackSuccess(TapCoreTracker.METHOD_LAUNCHER, sessionId, TapCoreTracker.SUCCESS_TYPE_RESTART);
TapLog.Log("IsLaunchedFromTapTapPC Quit game");
Application.Quit();
return false;
}
else
{
if (result.result == (int)TapSDKInitResult.OK)
{
string currentClientId;
bool isFetchClientIdSuccess = TapClientBridge.GetClientId(out currentClientId);
TapLog.Log("IsLaunchedFromTapTapPC get clientId = " + currentClientId);
if (isFetchClientIdSuccess && !string.IsNullOrEmpty(currentClientId) && currentClientId != clientId)
{
UIManager.Instance.OpenToast("SDK 中配置的 clientId = " + clientId + "与 Tap 启动器中" + currentClientId + "不一致", UIManager.GeneralToastLevel.Error);
TapLog.Error("SDK 中配置的 clientId = " + clientId + "与 Tap 启动器中" + currentClientId + "不一致");
TapCoreTracker.Instance.TrackFailure(TapCoreTracker.METHOD_LAUNCHER, sessionId, -1, "SDK 中配置的 clientId = " + clientId + "与 Tap 启动器中" + currentClientId + "不一致");
lastIsLaunchedFromTapTapPCResult = 0;
return false;
}
string openId;
bool fetchOpenIdSuccess = TapClientBridge.GetTapUserOpenId(out openId);
if (fetchOpenIdSuccess)
{
TapLog.Log("IsLaunchedFromTapTapPC get openId = " + openId);
EventManager.TriggerEvent(EventManager.IsLaunchedFromTapTapPCFinished, openId);
}
else
{
TapLog.Log("IsLaunchedFromTapTapPC get openId failed");
}
lastIsLaunchedFromTapTapPCResult = 1;
TapClientBridgePoll.StartUp();
TapCoreTracker.Instance.TrackSuccess(TapCoreTracker.METHOD_LAUNCHER, sessionId, TapCoreTracker.SUCCESS_TYPE_INIT);
TapLog.Log("IsLaunchedFromTapTapPC check success");
return true;
}
else
{
TapCoreTracker.Instance.TrackFailure(TapCoreTracker.METHOD_LAUNCHER, sessionId, (int)result.result, result.errorMsg ?? "");
lastIsLaunchedFromTapTapPCResult = 0;
TapLog.Log("IsLaunchedFromTapTapPC show TapClient tip Pannel " + result.result + " , error = " + result.errorMsg);
string tipPannelPath = "Prefabs/TapClient/TapClientConnectTipPanel";
if (Resources.Load(tipPannelPath) != null)
{
var pannel = UIManager.Instance.OpenUI(tipPannelPath);
pannel.Show(result.result);
}
return false;
}
}
}
catch (Exception e)
{
lastIsLaunchedFromTapTapPCResult = 0;
TapCoreTracker.Instance.TrackFailure(TapCoreTracker.METHOD_LAUNCHER, sessionId, (int)TapSDKInitResult.Unknown, e.Message ?? "");
TapLog.Log("IsLaunchedFromTapTapPC check exception = " + e.Message + " \n" + e.StackTrace);
string tipPannelPath = "Prefabs/TapClient/TapClientConnectTipPanel";
if (Resources.Load(tipPannelPath) != null)
{
var pannel = UIManager.Instance.OpenUI(tipPannelPath);
pannel.Show((int)TapSDKInitResult.Unknown);
}
return false;
}
}
private static async Task RunClientBridgeMethod(string clientId, string pubKey)
{
TaskCompletionSource task = new TaskCompletionSource();
try
{
await Task.Run(() =>
{
TapLog.Log( "check startupWithClientBridge start thread = " + Thread.CurrentThread.ManagedThreadId);
bool needQuitGame = TapClientBridge.TapSDK_RestartAppIfNecessary(clientId);
TapLog.Log("RunClientBridgeMethodWithTimeout invoke TapSDK_RestartAppIfNecessary result = " + needQuitGame);
TapLog.Log("RunClientBridgeMethodWithTimeout invoke TapSDK_RestartAppIfNecessary finished " );
if (needQuitGame)
{
tapInitResult = new TapInitResult(needQuitGame);
}
else
{
string outputError;
int tapSDKInitResult = TapClientBridge.CheckInitState(out outputError, pubKey);
TapLog.Log("RunClientBridgeMethodWithTimeout invoke CheckInitState result = " + tapSDKInitResult + ", error = " + outputError);
tapInitResult = new TapInitResult(tapSDKInitResult, outputError);
}
task.TrySetResult(tapInitResult);
});
}
catch (Exception ex)
{
TapLog.Log("RunClientBridgeMethodWithTimeout invoke C 方法出错!" + ex.Message);
task.TrySetException(ex);
}
return await task.Task;
}
///
/// 是否需要从启动器登录
///
public static bool IsNeedLoginByTapClient()
{
return isChannelPackage;
}
public static bool isPassedInLaunchedFromTapTapPCCheck(){
return lastIsLaunchedFromTapTapPCResult > 0;
}
private static Action currentLoginCallback;
///
/// 发起登录授权
///
public static bool StartLoginWithScopes(string[] scopes, string responseType, string redirectUri,
string codeChallenge, string state, string codeChallengeMethod, string versonCode, string sdkUa, string info, Action callback)
{
if (lastIsLaunchedFromTapTapPCResult == -1)
{
// UIManager.Instance.OpenToast("IsLaunchedFromTapTapPC 正在执行,请在完成后调用授权接口", UIManager.GeneralToastLevel.Error);
TapLog.Error(" login must be invoked after IsLaunchedFromTapTapPC success");
throw new Exception("login must be invoked after IsLaunchedFromTapTapPC success");
}
TapLog.Log("LoginWithScopes start login by tapclient thread = " + Thread.CurrentThread.ManagedThreadId);
try
{
TapClientBridge.RegisterCallback(TapEventID.AuthorizeFinished_internal, loginCallbackDelegate);
AuthorizeResult authorizeResult = TapClientBridge.LoginWithScopesInternal(scopes, responseType, redirectUri,
codeChallenge, state, codeChallengeMethod, versonCode, sdkUa, info);
TapLog.Log("LoginWithScopes start result = " + authorizeResult);
if (authorizeResult != AuthorizeResult.OK)
{
TapClientBridge.UnRegisterCallback(TapEventID.AuthorizeFinished_internal,loginCallbackDelegate);
return false;
}
else
{
currentLoginCallback = callback;
return true;
}
}
catch (Exception ex)
{
TapLog.Log("LoginWithScopes start login by tapclient error = " + ex.Message);
TapClientBridge.UnRegisterCallback(TapEventID.AuthorizeFinished_internal,loginCallbackDelegate);
return false;
}
}
[AOT.MonoPInvokeCallback(typeof(TapClientBridge.CallbackDelegate))]
static void loginCallbackDelegate(int id, IntPtr userData)
{
TapLog.Log("LoginWithScopes recevie callback " + id);
if (id == (int)TapEventID.AuthorizeFinished_internal)
{
TapLog.Log("LoginWithScopes callback thread = " + Thread.CurrentThread.ManagedThreadId);
TapClientBridge.AuthorizeFinishedResponse response = Marshal.PtrToStructure(userData);
TapLog.Log("LoginWithScopes callback = " + response.is_cancel + " uri = " + response.callback_uri);
if (currentLoginCallback != null)
{
currentLoginCallback(response.is_cancel != 0, response.callback_uri);
TapClientBridge.UnRegisterCallback(TapEventID.AuthorizeFinished_internal,loginCallbackDelegate);
currentLoginCallback = null;
}
}
}
// DLC 相关功能
private static Action currentDlcDelegate;
private static Action currentLicenseDelegate;
/// 查询是否购买 DLC , 未调用 isLaunchFromPC 会抛异常
public static bool QueryDLC(string skuId)
{
if (lastIsLaunchedFromTapTapPCResult != 1)
{
throw new Exception("queryDLC must be invoked after IsLaunchedFromTapTapPC success");
}
bool success = TapClientBridge.QueryDLC(skuId);
return success;
}
/// 跳转到 TapTap 客户端 DLC 购买页面 , 未调用 isLaunchFromPC 会抛异常
public static bool ShowStore(string skuId)
{
if (lastIsLaunchedFromTapTapPCResult != 1)
{
throw new Exception("purchaseDLC must be invoked after IsLaunchedFromTapTapPC success");
}
TapLog.Log("purchaseDLC start = " + skuId);
return TapClientBridge.TapDLC_ShowStore(skuId);
}
/// 注册 DLC 购买状态变更回调,包括购买成功和退款
public static void RegisterDLCOwnedCallback(Action dlcDelegate)
{
currentDlcDelegate = dlcDelegate;
TapClientBridge.RegisterCallback(TapEventID.DLCPlayableStatusChanged, DLCCallbackDelegate);
}
/// DLC 回调
[AOT.MonoPInvokeCallback(typeof(TapClientBridge.CallbackDelegate))]
static void DLCCallbackDelegate(int id, IntPtr userData)
{
TapLog.Log("queryDlC recevie callback " + id);
if (currentDlcDelegate != null)
{
TapClientBridge.DLCPlayableStatusChangedResponse response = Marshal.PtrToStructure(userData);
TapLog.Log("queryDlC callback = " + response.dlc_id + " isOwn = " + response.is_playable);
currentDlcDelegate(response.dlc_id, response.is_playable != 0);
}
}
/// 注册 License 购买状态变更回调,包括购买成功和退款
public static void RegisterLicenseCallback(Action licensecDelegate)
{
currentLicenseDelegate = licensecDelegate;
TapClientBridge.RegisterCallback(TapEventID.GamePlayableStatusChanged, LicenseCallbackDelegate);
}
/// License 回调
[AOT.MonoPInvokeCallback(typeof(TapClientBridge.CallbackDelegate))]
static void LicenseCallbackDelegate(int id, IntPtr userData)
{
TapLog.Log("License recevie callback " + id);
if (currentLicenseDelegate != null)
{
TapClientBridge.GamePlayableStatusChangedResponse response = Marshal.PtrToStructure(userData);
TapLog.Log("License callback isOwn changed " + response.is_playable );
currentLicenseDelegate(response.is_playable != 0);
}
}
public static bool HasLicense()
{
if (lastIsLaunchedFromTapTapPCResult != 1)
{
throw new Exception("checkLicense must be invoked after IsLaunchedFromTapTapPC success");
}
return TapClientBridge.HasLicense();
}
// 初始化校验结果
private class TapInitResult
{
internal int result;
internal string errorMsg;
internal bool needQuitGame = false;
public TapInitResult(int result, string errorMsg)
{
this.result = result;
this.errorMsg = errorMsg;
}
public TapInitResult(bool needQuitGame)
{
this.needQuitGame = needQuitGame;
}
}
}
#endif
}