616 lines
20 KiB
C#
616 lines
20 KiB
C#
// #######
|
|
// # # #### # # # # # ####
|
|
// # # # # # # ## # # #
|
|
// ##### # #### ###### # # # # #
|
|
// # # # # # # # # # # ###
|
|
// # # # # # # # # ## # #
|
|
// # # #### # # # # # ####
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using asap.core;
|
|
using game;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
using Task = System.Threading.Tasks.Task;
|
|
using UnityEngine.AddressableAssets;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using System.Collections.Generic;
|
|
//using HybridCLR;
|
|
using tysdk;
|
|
using System.Collections;
|
|
|
|
public class Boostrap : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private RootCtx ctx;
|
|
|
|
private IConfig config;
|
|
|
|
[SerializeField]
|
|
private BoostrapLoading bsLoading;
|
|
|
|
[SerializeField]
|
|
private SimpleDialog reconnectDialog;
|
|
|
|
[SerializeField]
|
|
|
|
private SimpleDialog updateDialog;
|
|
|
|
[SerializeField]
|
|
private SimpleDialog updateSugetDialog;
|
|
|
|
[SerializeField]
|
|
private SimpleDialog maintanceDialog;
|
|
|
|
[SerializeField]
|
|
private AgreementsPolicesPanel agreementPanel;
|
|
|
|
[SerializeField]
|
|
private AssetLabelReference preloadGroup;
|
|
|
|
private System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
|
|
|
private double elapsed;
|
|
|
|
void Start()
|
|
{
|
|
//This will override OS specific culture
|
|
//settings and ensure predictable behavior when writing/reading string or text files.
|
|
System.Globalization.CultureInfo.DefaultThreadCurrentCulture
|
|
= new System.Globalization.CultureInfo("en-US");
|
|
ctx.OnInited += OnContextInited;
|
|
bsLoading.Show();
|
|
bsLoading.SetProgress(0);
|
|
bsLoading.SetDownloadSize(-1, -1);
|
|
}
|
|
|
|
// Callback from GContex when its ready
|
|
private void OnContextInited()
|
|
{
|
|
config = GContext.container.Resolve<IConfig>();
|
|
Boost();
|
|
ctx.OnInited = null;
|
|
}
|
|
|
|
|
|
private async void Boost()
|
|
{
|
|
Boostrapi18n.Instance.Init();
|
|
bsLoading.SetInfo(Boostrapi18n.Instance.GetText("msg_initializing"));
|
|
|
|
if(! await agreementPanel.Agreement())
|
|
{
|
|
RootCtx.ExitGame();
|
|
return;
|
|
}
|
|
|
|
tysdk.UnityBridgeFunc.RequestATT();
|
|
|
|
if (!await CheckNetwork())
|
|
{
|
|
await RetryDialog(reconnectDialog, CheckNetwork, "network");
|
|
}
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
// __ _
|
|
// _____ _____ _____ _____ ___ ___ _ __ / _(_) __ _ _____ _____ _____
|
|
//|_____|_____|_____|_____| / __/ _ \| '_ \| |_| |/ _` | |_____|_____|_____|
|
|
//|_____|_____|_____|_____| | (_| (_) | | | | _| | (_| | |_____|_____|_____|
|
|
// \___\___/|_| |_|_| |_|\__, |
|
|
// |___/
|
|
|
|
#if AGG
|
|
using (var e = GEvent.TackEvent("loading"))
|
|
{
|
|
e.AddContent("step", 1);
|
|
e.AddContent("elapsed", 0);
|
|
}
|
|
#endif
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
sw.Start();
|
|
|
|
// if (!await LoadConfig())
|
|
// await RetryDialog(reconnectDialog, LoadConfig, "config");
|
|
var isSuccessLoadRemoteConfigFile = await LoadConfig();
|
|
|
|
sw.Stop();
|
|
elapsed = sw.Elapsed.TotalSeconds;
|
|
sw.Reset();
|
|
|
|
|
|
#if AGG
|
|
using (var e = GEvent.TackEvent("loading"))
|
|
{
|
|
e.AddContent("step", 2);
|
|
e.AddContent("elapsed", elapsed);
|
|
}
|
|
#endif
|
|
await Awaiters.NextFrame;
|
|
|
|
|
|
var maintanceMsg = config.Get(GConstant.K_Maintance, string.Empty);
|
|
if (!string.IsNullOrEmpty(maintanceMsg))
|
|
{
|
|
ShowMantainceDialog(maintanceMsg);
|
|
return;
|
|
}
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
|
|
if (!await CheckVerion())
|
|
{
|
|
return;
|
|
}
|
|
#if AGG
|
|
// Change AGG server
|
|
var aggserver = config.Get("AGG_SERVER", string.Empty);
|
|
|
|
if (!string.IsNullOrEmpty(aggserver))
|
|
{
|
|
//更新服务器
|
|
UnityBridgeFunc.UnityResetServerUrl(aggserver);
|
|
}
|
|
|
|
#endif
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
/*
|
|
*
|
|
* _ _ _
|
|
* _____ _____ _____ _____ (_)___ ___ _ __ __| | __ _| |_ __ _ _____ _____ _____
|
|
*|_____|_____|_____|_____| | / __|/ _ \| '_ \ / _` |/ _` | __/ _` | |_____|_____|_____|
|
|
*|_____|_____|_____|_____| | \__ \ (_) | | | | | (_| | (_| | || (_| | |_____|_____|_____|
|
|
* _/ |___/\___/|_| |_| \__,_|\__,_|\__\__,_|
|
|
* |__/
|
|
*/
|
|
|
|
#if !UNITY_EDITOR
|
|
|
|
sw.Start();
|
|
|
|
// if (!await UpdateCfg(isSuccessLoadRemoteConfigFile))
|
|
// await RetryDialog(reconnectDialog, UpdateCfg, "cfg");
|
|
await UpdateCfg(isSuccessLoadRemoteConfigFile);
|
|
|
|
sw.Stop();
|
|
elapsed = sw.Elapsed.TotalSeconds;
|
|
sw.Reset();
|
|
|
|
#if AGG
|
|
using (var e = GEvent.TackEvent("loading"))
|
|
{
|
|
e.AddContent("step", 3);
|
|
e.AddContent("elapsed", elapsed);
|
|
}
|
|
#endif //AGG
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
#endif // !UNITY_EDITOR
|
|
|
|
/*
|
|
* _ _ _
|
|
* _____ _____ _____ _____ / \ __| | __| |_ __ _____ _____ _____
|
|
*|_____|_____|_____|_____| / _ \ / _` |/ _` | '__| |_____|_____|_____|
|
|
*|_____|_____|_____|_____| / ___ \ (_| | (_| | | |_____|_____|_____|
|
|
* /_/ \_\__,_|\__,_|_|
|
|
*/
|
|
|
|
/* sw.Start(); */
|
|
/**/
|
|
/* Addressables.WebRequestOverride = (UnityWebRequest request) => request.timeout = 15; */
|
|
/**/
|
|
/* while(!await UpdateAsset()) */
|
|
/* { */
|
|
/* #if AGG */
|
|
/* using (var e = GEvent.TackEvent("retry")) */
|
|
/* { */
|
|
/* e.AddContent("type", "update"); */
|
|
/* } */
|
|
/* #endif */
|
|
/* Debug.LogWarning("UpdateAsset failed"); */
|
|
/* } */
|
|
/**/
|
|
/* sw.Stop(); */
|
|
/* elapsed = sw.Elapsed.TotalSeconds; */
|
|
/* sw.Reset(); */
|
|
/**/
|
|
/* #if AGG */
|
|
/* using (var e = GEvent.TackEvent("loading")) */
|
|
/* { */
|
|
/* e.AddContent("step", 5); */
|
|
/* e.AddContent("elapsed", elapsed); */
|
|
/* } */
|
|
/* #endif */
|
|
|
|
/*
|
|
sw.Start();
|
|
await AfterAssetUpdate();
|
|
|
|
sw.Stop();
|
|
elapsed = sw.Elapsed.TotalSeconds;
|
|
sw.Reset();
|
|
*/
|
|
|
|
/*
|
|
* _
|
|
* _____ _____ _____ _____ ___ ___| |_ _ _ _ __ _____ _____ _____
|
|
*|_____|_____|_____|_____| / __|/ _ \ __| | | | '_ \ |_____|_____|_____|
|
|
*|_____|_____|_____|_____| \__ \ __/ |_| |_| | |_) | |_____|_____|_____|
|
|
* |___/\___|\__|\__,_| .__/
|
|
* |_|
|
|
*/
|
|
|
|
await AfterAssetUpdateV2();
|
|
|
|
#if AGG
|
|
using (var e = GEvent.TackEvent("loading"))
|
|
{
|
|
e.AddContent("step", 6);
|
|
e.AddContent("elapsed", elapsed);
|
|
}
|
|
#endif
|
|
//StopUpdateLoadingInfo();
|
|
await GoToStageV2();
|
|
}
|
|
|
|
private async Task<bool> CheckNetwork()
|
|
{
|
|
await Awaiters.NextFrame;
|
|
return Application.internetReachability != NetworkReachability.NotReachable;
|
|
}
|
|
|
|
private async Task<bool> LoadConfig()
|
|
{
|
|
var success = await config.InitConfig();
|
|
|
|
// Change Addressable remote location, using custom assetbundle server
|
|
var customAddressableRemoteURL = config.Get(GConstant.K_Custom_Addressable, string.Empty);
|
|
var originAddressableRemoteURL = config.Get(GConstant.K_Origin_Addressable, string.Empty);
|
|
if (!string.IsNullOrEmpty(customAddressableRemoteURL)
|
|
&& !string.IsNullOrEmpty(originAddressableRemoteURL))
|
|
{
|
|
ctx.ChangeAddressableRemoteUrl(customAddressableRemoteURL, originAddressableRemoteURL);
|
|
}
|
|
|
|
await Awaiters.NextFrame;
|
|
bsLoading.SetProgress(0.02f);
|
|
|
|
Debug.Log($"[Boostrap]::LoadConfig Done success: {success}");
|
|
return success;
|
|
}
|
|
|
|
private async Task<bool> UpdateCfg(bool isSuccessLoadRemoteConfigFile)
|
|
{
|
|
var result = await cfg.Tables.UpdateCfg(config, isSuccessLoadRemoteConfigFile);
|
|
bsLoading.SetProgress(0.05f);
|
|
return result;
|
|
}
|
|
|
|
private async Task<bool> CheckVerion()
|
|
{
|
|
var remoteVer = VersionTool.FromString(config.Get(GConstant.K_Ver, string.Empty));
|
|
var localVer = VersionTool.FromLocal();
|
|
if (remoteVer > localVer)
|
|
{
|
|
updateDialog.Config(new SimpleDialog.Context()
|
|
{
|
|
message = Boostrapi18n.Instance.GetText("title_hardupdate"),
|
|
message2 = Boostrapi18n.Instance.GetText("content_hardupdate"),
|
|
okAction = () =>
|
|
{
|
|
#if UNITY_IOS
|
|
var url = config.Get(GConstant.K_APP_Store_URL, string.Empty);
|
|
#else
|
|
var url = config.Get(GConstant.K_Google_Play_URL, string.Empty);
|
|
#endif
|
|
Application.OpenURL(url);
|
|
RootCtx.ExitGame();
|
|
}
|
|
});
|
|
return false;
|
|
}
|
|
|
|
var newVer = config.Get(GConstant.K_Ver_New, string.Empty);
|
|
if (!string.IsNullOrEmpty(newVer))
|
|
{
|
|
var confirm = new TaskCompletionSource<bool>();
|
|
updateSugetDialog.Config(new SimpleDialog.Context()
|
|
{
|
|
message = Boostrapi18n.Instance.GetText("title_hardupdate"),
|
|
message2 = Boostrapi18n.Instance.GetText("content_hardupdate"),
|
|
okAction = () =>
|
|
{
|
|
|
|
#if UNITY_IOS
|
|
var url = config.Get(GConstant.K_APP_Store_URL, string.Empty);
|
|
#else
|
|
var url = config.Get(GConstant.K_Google_Play_URL, string.Empty);
|
|
#endif
|
|
Application.OpenURL(url);
|
|
confirm.SetResult(false);
|
|
RootCtx.ExitGame();
|
|
},
|
|
|
|
closeAction = () =>
|
|
{
|
|
confirm.SetResult(true);
|
|
}
|
|
});
|
|
|
|
return await confirm.Task;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private async Task<bool> UpdateAsset()
|
|
{
|
|
#if UNITY_EDITOR
|
|
await Awaiters.NextFrame;
|
|
return true;
|
|
#else
|
|
await Awaiters.NextFrame;
|
|
bsLoading.SetVersionInfo(VersionTool.FromLocal().ToVerString());
|
|
|
|
try
|
|
{
|
|
Debug.Log("Start UpdateAsset");
|
|
//Addressables.WebRequestOverride = (UnityWebRequest request) => request.timeout = 6;
|
|
List<string> update_catalogs = null;
|
|
var updateCheckHandle = Addressables.CheckForCatalogUpdates(false);
|
|
|
|
update_catalogs = await updateCheckHandle.Task;
|
|
|
|
if(updateCheckHandle.OperationException != null || updateCheckHandle.Status == AsyncOperationStatus.Failed)
|
|
{
|
|
Debug.LogError($"update checked failed: { updateCheckHandle.OperationException.Message }");
|
|
return false;
|
|
}
|
|
Addressables.Release(updateCheckHandle);
|
|
|
|
if(null != update_catalogs)
|
|
{
|
|
Debug.Log($"update catalogs count: {update_catalogs.Count}");
|
|
}
|
|
|
|
if(null != update_catalogs && update_catalogs.Count > 0)
|
|
{
|
|
var updateCatalogHandle = Addressables.UpdateCatalogs(update_catalogs, false);
|
|
await updateCatalogHandle.Task;
|
|
if(updateCatalogHandle.OperationException != null || updateCatalogHandle.Status == AsyncOperationStatus.Failed)
|
|
{
|
|
Debug.LogError($"update catalogs failed: {updateCatalogHandle.OperationException.Message}");
|
|
return false;
|
|
}
|
|
Addressables.Release(updateCatalogHandle);
|
|
}
|
|
|
|
var locationsHandle = Addressables.LoadResourceLocationsAsync(preloadGroup.labelString);
|
|
var locations = await locationsHandle.Task;
|
|
if(locationsHandle.OperationException != null || locationsHandle.Status == AsyncOperationStatus.Failed)
|
|
{
|
|
Debug.LogError($"load resource locations failed: {locationsHandle.OperationException.Message}");
|
|
return false;
|
|
}
|
|
Addressables.Release(locationsHandle);
|
|
|
|
var downloadSizeHandle = Addressables.GetDownloadSizeAsync(locations);
|
|
var downloadSize = await downloadSizeHandle.Task;
|
|
if(downloadSizeHandle.OperationException != null || downloadSizeHandle.Status == AsyncOperationStatus.Failed)
|
|
{
|
|
Debug.LogError($"get download size failed: {downloadSizeHandle.OperationException.Message}");
|
|
return false;
|
|
}
|
|
Addressables.Release(downloadSizeHandle);
|
|
|
|
if(downloadSize > 0)
|
|
{
|
|
bsLoading.SetInfo(Boostrapi18n.Instance.GetText("msg_downloading"));
|
|
var downloadHandle = Addressables.DownloadDependenciesAsync(locations);
|
|
|
|
DownloadStatus downloadStatus;
|
|
long downloadedBytes = 0;
|
|
float percent = 0;
|
|
|
|
while (!downloadHandle.IsDone && downloadHandle.OperationException == null && downloadHandle.Status != AsyncOperationStatus.Failed)
|
|
{
|
|
downloadStatus = downloadHandle.GetDownloadStatus();
|
|
if(downloadStatus.DownloadedBytes > downloadedBytes)
|
|
downloadedBytes = downloadStatus.DownloadedBytes;
|
|
if(downloadStatus.Percent > percent)
|
|
percent = downloadStatus.Percent;
|
|
bsLoading.SetProgress(percent);
|
|
bsLoading.SetInfo(Boostrapi18n.Instance.GetText("msg_downloading"));
|
|
bsLoading.SetDownloadSize(downloadedBytes, downloadStatus.TotalBytes);
|
|
//bsLoading.SetSubProgress(downloadHandle.PercentComplete);
|
|
await Awaiters.NextFrame;
|
|
}
|
|
|
|
if(downloadHandle.OperationException != null)
|
|
{
|
|
Debug.LogError($"Download Fail: {downloadHandle.OperationException.Message}");
|
|
return false;
|
|
}
|
|
|
|
if(downloadHandle.Status == AsyncOperationStatus.Failed)
|
|
{
|
|
Debug.LogError($"Download Fail Status: {downloadHandle.Status}");
|
|
return false;
|
|
}
|
|
|
|
downloadStatus = downloadHandle.GetDownloadStatus();
|
|
if(downloadStatus.TotalBytes == 0 && downloadStatus.DownloadedBytes == 0)
|
|
{
|
|
Debug.LogError($"Download Fail: {downloadStatus.TotalBytes} {downloadStatus.DownloadedBytes}");
|
|
return false;
|
|
}
|
|
|
|
Addressables.Release(downloadHandle);
|
|
}
|
|
|
|
//bsLoading.SetSubProgress(-1);
|
|
}
|
|
catch(System.Exception e)
|
|
{
|
|
Debug.LogError($"[Boostrap]::UpdateAsset error: {e.Message}");
|
|
return false;
|
|
}
|
|
//finally
|
|
//{
|
|
//Addressables.WebRequestOverride = null;
|
|
//}
|
|
|
|
bsLoading.SetProgress(0.1f);
|
|
bsLoading.SetInfo(Boostrapi18n.Instance.GetText("msg_loadingresource"));
|
|
|
|
await Awaiters.NextFrame;
|
|
|
|
var remoteVer = VersionTool.FromString(config.Get(GConstant.K_Ver, string.Empty));
|
|
remoteVer.Save();
|
|
bsLoading.SetVersionInfo(remoteVer.ToVerString());
|
|
|
|
await Awaiters.NextFrame;
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
private async Task AfterAssetUpdateV2()
|
|
{
|
|
bsLoading.SetProgress(0.15f);
|
|
await SubBoostrap.RegisterServices(ctx.gameObject);
|
|
bsLoading.SetProgress(0.16f);
|
|
await SubBoostrap.AfterAssetUpdate(config, bsLoading.SetProgress);
|
|
bsLoading.SetProgress(0.18f);
|
|
}
|
|
|
|
private async Task GoToStageV2()
|
|
{
|
|
Debug.Log("Boostrap Done");
|
|
|
|
await SubBoostrap.ShowLoadingScreen(config, ctx.gameObject);
|
|
await Awaiters.NextFrame;
|
|
bsLoading.Hide();
|
|
_ = GContext.container.Resolve<IStageService>().SwitchStageAsync("LoginStage");
|
|
}
|
|
|
|
|
|
/*
|
|
private Type _hotUpdateBoostrapType;
|
|
private async Task AfterAssetUpdate()
|
|
{
|
|
var hotUpdateAsset = await LoadDll();
|
|
bsLoading.SetProgress(0.15f);
|
|
|
|
|
|
Debug.Log($"[Boostrap]::AfterAssetUpdate LoadDll Done");
|
|
|
|
_hotUpdateBoostrapType = hotUpdateAsset.GetType("HotUpateBoostrap");
|
|
|
|
var task = (Task)_hotUpdateBoostrapType.GetMethod("RegisterServices").Invoke(null, new object[] { ctx.gameObject });
|
|
await task;
|
|
|
|
bsLoading.SetProgress(0.16f);
|
|
|
|
var progressAction = Delegate.CreateDelegate(typeof(Action<float>), bsLoading, "SetProgress");
|
|
|
|
task = (Task)_hotUpdateBoostrapType.GetMethod("AfterAssetUpdate").Invoke(null, new object[] { config, progressAction });
|
|
|
|
await task;
|
|
|
|
Debug.Log($"[Boostrap]::AfterAssetUpdate RegisterServices Done");
|
|
|
|
bsLoading.SetProgress(0.18f);
|
|
}
|
|
|
|
private async Task<Assembly> LoadDll()
|
|
{
|
|
#if !UNITY_EDITOR
|
|
//Load HotUpdate dll
|
|
var dllAsset = await Addressables.LoadAssetAsync<TextAsset>("Hotupdate.dll").Task;
|
|
var bytes = dllAsset.bytes;
|
|
var hotUpdateAsset = Assembly.Load(bytes);
|
|
Addressables.Release(dllAsset);
|
|
|
|
//Load Aot dll
|
|
var aotDllTasks = GConstant.AOT_Dlls.Select(aotDllName => Addressables.LoadAssetAsync<TextAsset>(aotDllName).Task);
|
|
await Task.WhenAll(aotDllTasks);
|
|
|
|
var dllLoadTasks = new List<Task>();
|
|
foreach (var aotDllTask in aotDllTasks)
|
|
{
|
|
var aotDllBytes = aotDllTask.Result.bytes;
|
|
dllLoadTasks.Add(Task.Run(() => {
|
|
HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly(aotDllBytes, HomologousImageMode.SuperSet);
|
|
}));
|
|
}
|
|
await Task.WhenAll(dllLoadTasks);
|
|
|
|
#else
|
|
|
|
var hotUpdateAsset = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
|
|
await Awaiters.NextFrame;
|
|
|
|
#endif
|
|
return hotUpdateAsset;
|
|
}
|
|
|
|
private async Task GoToStage()
|
|
{
|
|
Debug.Log("Boostrap Done");
|
|
|
|
var task = (Task)_hotUpdateBoostrapType.GetMethod("ShowLoadingScreen").Invoke(null, new object[] { config });
|
|
await task;
|
|
await Awaiters.NextFrame;
|
|
bsLoading.Hide();
|
|
_ = GContext.container.Resolve<IStageService>().SwitchStageAsync("LoginStage");
|
|
}
|
|
*/
|
|
|
|
|
|
void OnDestory()
|
|
{
|
|
ctx.OnInited -= OnContextInited;
|
|
}
|
|
|
|
private void ShowMantainceDialog(string maintanceMessage)
|
|
{
|
|
maintanceDialog.Config(new SimpleDialog.Context()
|
|
{
|
|
message = Boostrapi18n.Instance.GetText("title_maintenance"),
|
|
message2 = string.Format(Boostrapi18n.Instance.GetText("content_maintenance"), maintanceMessage),
|
|
okAction = () => RootCtx.ExitGame(),
|
|
});
|
|
}
|
|
|
|
private async Task RetryDialog(SimpleDialog dialog, Func<Task<bool>> func, string retryType)
|
|
{
|
|
while (true)
|
|
{
|
|
|
|
#if AGG
|
|
using (var e = GEvent.TackEvent("retry"))
|
|
{
|
|
e.AddContent("type", retryType);
|
|
}
|
|
#endif
|
|
var retry = new TaskCompletionSource<bool>();
|
|
dialog.Config(new SimpleDialog.Context()
|
|
{
|
|
message = Boostrapi18n.Instance.GetText("subtitle_networkfailed"),
|
|
message2 = Boostrapi18n.Instance.GetText("content_networkfailed"),
|
|
okAction = async () => retry.SetResult(await func()),
|
|
});
|
|
if (await retry.Task) return;
|
|
}
|
|
}
|
|
}
|
|
|