VersionController.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using GFGGame.Launcher;
  2. using VEngine;
  3. using System.Collections;
  4. using UnityEngine;
  5. using System.Reflection;
  6. namespace GFGGame
  7. {
  8. public class VersionController : SingletonMonoBase<VersionController>
  9. {
  10. private UpdateVersions updateVersions;
  11. public void Init()
  12. {
  13. StartCoroutine(InitVersion());
  14. }
  15. public IEnumerator InitVersion()
  16. {
  17. Versions.DownloadURL = LauncherConfig.CDN_ROOT;
  18. var operation = Versions.InitializeAsync(LauncherConfig.CDN_ROOT);
  19. yield return operation;
  20. VEngine.Logger.I("Initialize: {0}", operation.status);
  21. VEngine.Logger.I("API Version: {0}", Versions.APIVersion);
  22. VEngine.Logger.I("AppVersion: {0}", Versions.Manifest.appVersion);
  23. VEngine.Logger.I("Manifests Version: {0}", Versions.ManifestsVersion);
  24. VEngine.Logger.I("PlayerDataPath: {0}", Versions.PlayerDataPath);
  25. VEngine.Logger.I("DownloadDataPath: {0}", Versions.DownloadDataPath);
  26. VEngine.Logger.I("DownloadURL: {0}", Versions.DownloadURL);
  27. StartUpdateManifest();
  28. }
  29. private void CheckApkVersion()
  30. {
  31. var versionTarget = Versions.Manifest.appVersion;
  32. var version = Application.version;
  33. if(VersionUtil.compare(version, versionTarget))
  34. {
  35. DownloadApk();
  36. }
  37. else
  38. {
  39. DownloadRes();
  40. }
  41. }
  42. private void StartUpdateManifest()
  43. {
  44. StartCoroutine(CheckManifestVersion());
  45. }
  46. private IEnumerator CheckManifestVersion()
  47. {
  48. if (!Versions.OfflineMode)
  49. {
  50. // TODO:生产环境这里的清单名字应该使用带 hash 的版本
  51. updateVersions = Versions.UpdateAsync(nameof(Manifest));
  52. while(!updateVersions.isDone)
  53. {
  54. if(updateVersions.asset != null && updateVersions.asset.assetVersion != null)
  55. {
  56. var max = updateVersions.asset.assetVersion.size;
  57. LauncherView.Instance.SetDesc($"获取版本文件...", $"{Utility.FormatBytes(max)}");
  58. LauncherView.Instance.SetProgress((int)(updateVersions.asset.progress * 100));
  59. }
  60. yield return updateVersions;
  61. };
  62. if (updateVersions.status == OperationStatus.Failed)
  63. {
  64. yield return Alert.Show("更新版本信息失败,请检测网络链接后重试。")
  65. .SetLeftButton(true, "重试", (data) => { StartUpdateManifest(); });
  66. yield break;
  67. }
  68. CheckApkVersion();
  69. yield break;
  70. }
  71. OnComplete();
  72. }
  73. private void DownloadApk()
  74. {
  75. Alert.Show("需要安装新的安装包,请联系研发获取。")
  76. .SetLeftButton(true, "知道了", (data) => {
  77. Application.Quit();
  78. });
  79. }
  80. private void DownloadRes()
  81. {
  82. StartCoroutine(GetDownloadSize());
  83. }
  84. private IEnumerator GetDownloadSize()
  85. {
  86. Debug.Log("VersionController GetDownloadSize");
  87. var getDownloadSize = Versions.GetDownloadSizeAsync(updateVersions);
  88. var totalCount = getDownloadSize.bundles.Count;
  89. while(!getDownloadSize.isDone)
  90. {
  91. var remainCount = getDownloadSize.bundles.Count;
  92. LauncherView.Instance.SetDesc($"正在计算更新内容大小...", $"{ totalCount - remainCount }/{totalCount}");
  93. yield return getDownloadSize;
  94. }
  95. Debug.Log("VersionController GetDownloadSize tips");
  96. if (getDownloadSize.totalSize > 0 || updateVersions.changed)
  97. {
  98. string message = $"游戏有新的版本,需要更新{Utility.FormatBytes(getDownloadSize.totalSize)}大小的内容";
  99. yield return Alert.Show(message)
  100. .SetLeftButton(true, "更新", (data) => {
  101. StartDownload(getDownloadSize);
  102. });
  103. yield break;
  104. }
  105. OnComplete();
  106. }
  107. private void StartDownload(GetDownloadSize getDownloadSize)
  108. {
  109. StartCoroutine(Downloading(getDownloadSize));
  110. }
  111. private IEnumerator Downloading(GetDownloadSize getDownloadSize)
  112. {
  113. LauncherView.Instance.SetProgress((int)(updateVersions.asset.progress * 100));
  114. var downloadAsync = Versions.DownloadAsync(getDownloadSize.result.ToArray());
  115. downloadAsync.updated += downloadAsync =>
  116. {
  117. var current = downloadAsync.downloadedBytes;
  118. var max = downloadAsync.totalSize;
  119. var speed = Download.TotalBandwidth;
  120. LauncherView.Instance.SetDesc($"正在下载资源,速度 {Utility.FormatBytes(speed)}/s", $"{Utility.FormatBytes(current)}/{Utility.FormatBytes(max)}");
  121. LauncherView.Instance.SetProgress((int)(downloadAsync.progress * 100));
  122. };
  123. yield return downloadAsync;
  124. if (downloadAsync.status == OperationStatus.Failed)
  125. {
  126. yield return Alert.Show("下载失败!请检查网络状态后重试。")
  127. .SetLeftButton(true, "重试", (data) => {
  128. StartDownload(getDownloadSize);
  129. });
  130. yield break;
  131. }
  132. OnComplete();
  133. }
  134. private void OnComplete()
  135. {
  136. if(updateVersions != null)
  137. {
  138. updateVersions.Override();
  139. }
  140. LauncherView.Instance.SetDesc($"正在启动游戏...");
  141. LauncherView.Instance.SetProgress(100, () =>
  142. {
  143. StartCoroutine(StartLoadAssemblyHotfix());
  144. });
  145. }
  146. IEnumerator StartLoadAssemblyHotfix()
  147. {
  148. Debug.LogFormat("ILRuntimeLauncher StartLoadAssemblyHotfix");
  149. yield return new WaitForSeconds(0.1f);
  150. var dllPath = "Assets/Res/Code/Game.HotUpdate.dll.bytes";
  151. var asset = GFGAsset.Load<TextAsset>(dllPath);
  152. byte[] assBytes = asset.bytes;
  153. //Debug.LogFormat("assBytes != null {0}", assBytes != null);
  154. //Debug.LogFormat("assBytes.Length {0}", assBytes.Length);
  155. //yield return new WaitForSeconds(0.1f);
  156. var pdbPath = "Assets/Res/Code/Game.HotUpdate.pdb.bytes";
  157. asset = GFGAsset.Load<TextAsset>(pdbPath);
  158. byte[] pdbBytes = asset.bytes;
  159. //Debug.LogFormat("pdbBytes != null {0}", pdbBytes != null);
  160. //Debug.LogFormat("pdbBytes.Length {0}", pdbBytes.Length);
  161. if(LauncherConfig.ILRuntimeMode)
  162. {
  163. Debug.LogFormat("Assembly Mode ILRuntime");
  164. ILRuntimeLauncher.Instance.LoadAssembly(assBytes, pdbBytes);
  165. }
  166. else
  167. {
  168. Debug.LogFormat("Assembly Mode Jit");
  169. StartCoroutine(LoadAssemblyJustInTime(assBytes, pdbBytes));
  170. }
  171. GFGAsset.Release(dllPath);
  172. GFGAsset.Release(pdbPath);
  173. }
  174. IEnumerator LoadAssemblyJustInTime(byte[] assBytes, byte[] pdbBytes)
  175. {
  176. //yield return new WaitForSeconds(0.1f);
  177. //mono模式
  178. var assembly = Assembly.Load(assBytes, pdbBytes);
  179. //Debug.LogFormat("assembly != null {0}", assembly != null);
  180. //yield return new WaitForSeconds(0.1f);
  181. System.Type type = assembly.GetType("GFGGame.HotUpdate.HotUpdateEntry");
  182. //Debug.LogFormat("type != null {0}", type != null);
  183. //yield return new WaitForSeconds(0.1f);
  184. type.GetMethod("Start").Invoke(type, null);
  185. yield break;
  186. }
  187. }
  188. }