VersionController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using GFGGame.Launcher;
  2. //using VEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using YooAsset;
  7. //using dnlib.PE;
  8. //using VEngine;
  9. //using UnityEngine.Events;
  10. namespace GFGGame
  11. {
  12. public class VersionController : SingletonMonoBase<VersionController>
  13. {
  14. //private UpdateVersions updateVersions;
  15. public const string DefaultPackage = "GameLogic";
  16. /// <summary>
  17. /// 包裹的版本信息
  18. /// </summary>
  19. public string PackageVersion { set; get; }
  20. public void Init()
  21. {
  22. // 初始化资源系统
  23. YooAssets.Initialize();
  24. StartCoroutine(InitVersion());
  25. }
  26. public IEnumerator InitVersion()
  27. {
  28. //VEngine.Logger.Loggable = false;
  29. //EncryptHelper.resKey = LauncherConfig.resKey;
  30. //Versions.DownloadURL = LauncherConfig.CDN_ROOT;
  31. //var operation = Versions.InitializeAsync(LauncherConfig.CDN_ROOT);
  32. //yield return operation;
  33. yield return InitDefaultPackage();
  34. yield return GetStaticVersion(DefaultPackage);
  35. yield return UpdateManifest(DefaultPackage);
  36. CreateDownloader(DefaultPackage);
  37. }
  38. private IEnumerator InitDefaultPackage()
  39. {
  40. // 创建默认的资源包
  41. string packageName = DefaultPackage;
  42. var package = YooAssets.TryGetPackage(packageName);
  43. if (package == null)
  44. {
  45. package = YooAssets.CreatePackage(packageName);
  46. YooAssets.SetDefaultPackage(package);
  47. }
  48. var playMode = GameLauncher.Instance.PlayMode;
  49. InitializationOperation initializationOperation = null;
  50. if (playMode == EPlayMode.EditorSimulateMode)
  51. {
  52. // 编辑器下的模拟模式
  53. var createParameters = new EditorSimulateModeParameters();
  54. createParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(packageName);
  55. initializationOperation = package.InitializeAsync(createParameters);
  56. }
  57. else if (playMode == EPlayMode.HostPlayMode)
  58. {
  59. // 联机运行模式
  60. string defaultHostServer = GetHostServerURL(DefaultPackage);
  61. string fallbackHostServer = defaultHostServer;
  62. var createParameters = new HostPlayModeParameters();
  63. //createParameters.DecryptionServices = new GameDecryptionServices();
  64. createParameters.QueryServices = new GameQueryServices();
  65. createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
  66. initializationOperation = package.InitializeAsync(createParameters);
  67. }
  68. yield return initializationOperation;
  69. if (initializationOperation.Status != EOperationStatus.Succeed)
  70. {
  71. Debug.LogWarning($"{initializationOperation.Error}");
  72. }
  73. }
  74. private IEnumerator GetStaticVersion(string packageName)
  75. {
  76. var package = YooAssets.GetPackage(packageName);
  77. var operation = package.UpdatePackageVersionAsync();
  78. yield return operation;
  79. if (operation.Status == EOperationStatus.Succeed)
  80. {
  81. VersionController.Instance.PackageVersion = operation.PackageVersion;
  82. Debug.Log($"远端最新版本为: {operation.PackageVersion}");
  83. }
  84. else
  85. {
  86. Debug.LogWarning(operation.Error);
  87. }
  88. }
  89. private IEnumerator UpdateManifest(string packageName)
  90. {
  91. bool savePackageVersion = true;
  92. var package = YooAssets.GetPackage(packageName);
  93. var operation = package.UpdatePackageManifestAsync(VersionController.Instance.PackageVersion, savePackageVersion);
  94. yield return operation;
  95. if (operation.Status != EOperationStatus.Succeed)
  96. {
  97. Debug.LogWarning(operation.Error);
  98. Alert.Show("更新版本信息失败,请检测网络链接后重试。")
  99. .SetLeftButton(true, "重试", (data) => { StartCoroutine(UpdateManifest(packageName)); });
  100. }
  101. }
  102. private void CreateDownloader(string packageName)
  103. {
  104. int downloadingMaxNum = 10;
  105. int failedTryAgain = 3;
  106. ResourcePackage package = YooAssets.GetPackage(packageName);
  107. var downloaderOperation = package.CreateResourceDownloader(new string[] { "preload" }, downloadingMaxNum, failedTryAgain);
  108. if (downloaderOperation.TotalDownloadCount == 0)
  109. {
  110. LauncherController.OnVersionCompleted();
  111. }
  112. else
  113. {
  114. //A total of 10 files were found that need to be downloaded
  115. Debug.Log($"Found total {downloaderOperation.TotalDownloadCount} files that need download !");
  116. // 发现新更新文件后,挂起流程系统
  117. // 注意:开发者需要在下载前检测磁盘空间不足
  118. int totalDownloadCount = downloaderOperation.TotalDownloadCount;
  119. long totalDownloadBytes = downloaderOperation.TotalDownloadBytes;
  120. float sizeMB = totalDownloadBytes / 1048576f;
  121. sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
  122. string totalSizeMB = sizeMB.ToString("f1");
  123. string message = $"游戏有新的内容,{packageName}需要更新{totalSizeMB}MB大小的内容";
  124. Alert.Show(message)
  125. .SetLeftButton(true, "更新", (data) =>
  126. {
  127. StartCoroutine(BeginDownload(downloaderOperation, packageName));
  128. });
  129. }
  130. }
  131. private IEnumerator BeginDownload(ResourceDownloaderOperation downloaderOperation, string packageName)
  132. {
  133. // 注册下载回调
  134. downloaderOperation.OnDownloadErrorCallback =
  135. (fileName, error) =>
  136. {
  137. Debug.LogError($"加载{fileName}失败 {error}");
  138. };
  139. downloaderOperation.OnDownloadProgressCallback =
  140. (totalDownloadCount, currentDownloadCount, totalDownloadSizeBytes, currentDownloadSizeBytes) =>
  141. {
  142. string currentSizeMB = (currentDownloadSizeBytes / 1048576f).ToString("f1");
  143. string totalSizeMB = (totalDownloadSizeBytes / 1048576f).ToString("f1");
  144. var progress = currentDownloadSizeBytes / totalDownloadSizeBytes;
  145. LauncherView.Instance.SetDesc($"正在下载资源,{currentDownloadCount}/{totalDownloadCount}", $"{currentSizeMB}MB/{totalSizeMB}MB", true);
  146. LauncherView.Instance.SetProgress((int)(progress * 100));
  147. };
  148. downloaderOperation.BeginDownload();
  149. yield return downloaderOperation;
  150. // 检测下载结果
  151. if (downloaderOperation.Status != EOperationStatus.Succeed)
  152. {
  153. Alert.Show("下载失败!请检查网络状态后重试。")
  154. .SetLeftButton(true, "重试", (data) =>
  155. {
  156. StartCoroutine(BeginDownload(downloaderOperation, packageName));
  157. });
  158. yield break;
  159. }
  160. LauncherController.OnVersionCompleted();
  161. }
  162. /// <summary>
  163. /// 获取资源服务器地址
  164. /// </summary>
  165. private string GetHostServerURL(string packageName)
  166. {
  167. string hostServerIP = "http://10.108.64.127";
  168. #if UNITY_EDITOR
  169. if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
  170. return $"{hostServerIP}/CDN/Android/{packageName}";
  171. else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
  172. return $"{hostServerIP}/CDN/IPhone/{packageName}";
  173. else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
  174. return $"{hostServerIP}/CDN/WebGL/{packageName}";
  175. else
  176. return $"{hostServerIP}/CDN/PC/{packageName}";
  177. #else
  178. if (Application.platform == RuntimePlatform.Android)
  179. return $"{hostServerIP}/CDN/Android/{packageName}";
  180. else if (Application.platform == RuntimePlatform.IPhonePlayer)
  181. return $"{hostServerIP}/CDN/IPhone/{packageName}";
  182. else if (Application.platform == RuntimePlatform.WebGLPlayer)
  183. return $"{hostServerIP}/CDN/WebGL/{packageName}";
  184. else
  185. return $"{hostServerIP}/CDN/PC/{packageName}";
  186. #endif
  187. }
  188. /// <summary>
  189. /// 远端资源地址查询服务类
  190. /// </summary>
  191. private class RemoteServices : IRemoteServices
  192. {
  193. private readonly string _defaultHostServer;
  194. private readonly string _fallbackHostServer;
  195. public RemoteServices(string defaultHostServer, string fallbackHostServer)
  196. {
  197. _defaultHostServer = defaultHostServer;
  198. _fallbackHostServer = fallbackHostServer;
  199. }
  200. string IRemoteServices.GetRemoteMainURL(string fileName)
  201. {
  202. return $"{_defaultHostServer}/{fileName}";
  203. }
  204. string IRemoteServices.GetRemoteFallbackURL(string fileName)
  205. {
  206. return $"{_fallbackHostServer}/{fileName}";
  207. }
  208. }
  209. //private void StartCheckManifestVersion()
  210. //{
  211. // StartCoroutine(CheckManifestVersion());
  212. //}
  213. //private IEnumerator CheckManifestVersion()
  214. //{
  215. // if (GameLauncher.Instance.PlayMode == EPlayMode.HostPlayMode)
  216. // {
  217. // LogServerHelperHttp.SendNodeLog((int)LogNode.StartCheckVersion);
  218. // // TODO:生产环境这里的清单名字应该使用带 hash 的版本
  219. // updateVersions = Versions.UpdateAsync(nameof(Manifest) + LauncherConfig.manifest_v);
  220. // while (!updateVersions.isDone)
  221. // {
  222. // if (updateVersions.asset != null && updateVersions.asset.assetVersion != null)
  223. // {
  224. // var max = updateVersions.asset.assetVersion.size;
  225. // LauncherView.Instance.SetDesc($"正在校验资源版本...", $"{Utility.FormatBytes(max)}");
  226. // LauncherView.Instance.SetProgress((int)(updateVersions.asset.progress * 100));
  227. // }
  228. // yield return updateVersions;
  229. // };
  230. // if (updateVersions.status == OperationStatus.Failed)
  231. // {
  232. // Alert.Show("更新版本信息失败,请检测网络链接后重试。")
  233. // .SetLeftButton(true, "重试", (data) => { StartCheckManifestVersion(); });
  234. // }
  235. // else
  236. // {
  237. // yield return GetDownloadSize();
  238. // }
  239. // }
  240. // else
  241. // {
  242. // OnComplete();
  243. // }
  244. //}
  245. //private IEnumerator GetDownloadSize()
  246. //{
  247. // var getDownloadSize = Versions.GetDownloadSizeAsync(updateVersions);
  248. // var totalCount = getDownloadSize.bundles.Count;
  249. // while(!getDownloadSize.isDone)
  250. // {
  251. // var remainCount = getDownloadSize.bundles.Count;
  252. // LauncherView.Instance.SetDesc($"正在计算更新内容大小...", $"{ totalCount - remainCount }/{totalCount}");
  253. // yield return getDownloadSize;
  254. // }
  255. // if (getDownloadSize.totalSize > 0 || updateVersions.changed)
  256. // {
  257. // string message = $"游戏有新的版本,需要更新{Utility.FormatBytes(getDownloadSize.totalSize)}大小的内容";
  258. // yield return Alert.Show(message)
  259. // .SetLeftButton(true, "更新", (data) => {
  260. // StartDownload(getDownloadSize);
  261. // });
  262. // yield break;
  263. // }
  264. // else
  265. // {
  266. // OnComplete();
  267. // }
  268. //}
  269. //private void StartDownload(GetDownloadSize getDownloadSize)
  270. //{
  271. // LogServerHelperHttp.SendNodeLog((int)LogNode.StartDownload);
  272. // StartCoroutine(Downloading(getDownloadSize));
  273. //}
  274. //private IEnumerator Downloading(GetDownloadSize getDownloadSize)
  275. //{
  276. // LauncherView.Instance.SetProgress((int)(updateVersions.asset.progress * 100));
  277. // var downloadAsync = Versions.DownloadAsync(getDownloadSize.result.ToArray());
  278. // downloadAsync.updated += downloadAsync =>
  279. // {
  280. // var current = downloadAsync.downloadedBytes;
  281. // var max = downloadAsync.totalSize;
  282. // var speed = Download.TotalBandwidth;
  283. // LauncherView.Instance.SetDesc($"正在下载资源,速度 {Utility.FormatBytes(speed)}/s", $"{Utility.FormatBytes(current)}/{Utility.FormatBytes(max)}", true);
  284. // LauncherView.Instance.SetProgress((int)(downloadAsync.progress * 100));
  285. // };
  286. // yield return downloadAsync;
  287. // if (downloadAsync.status == OperationStatus.Failed)
  288. // {
  289. // Alert.Show("下载失败!请检查网络状态后重试。")
  290. // .SetLeftButton(true, "重试", (data) => {
  291. // StartDownload(getDownloadSize);
  292. // });
  293. // }
  294. // else
  295. // {
  296. // OnComplete();
  297. // }
  298. //}
  299. }
  300. }