UpdatePackageOperation.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. namespace YooAsset
  6. {
  7. public abstract class UpdatePackageOperation : AsyncOperationBase
  8. {
  9. /// <summary>
  10. /// 创建包裹下载器
  11. /// </summary>
  12. /// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
  13. /// <param name="failedTryAgain">下载失败的重试次数</param>
  14. public abstract PackageDownloaderOperation CreatePackageDownloader(int downloadingMaxNumber, int failedTryAgain);
  15. }
  16. /// <summary>
  17. /// 编辑器下模拟运行的更新资源包裹操作
  18. /// </summary>
  19. internal sealed class EditorPlayModeUpdatePackageOperation : UpdatePackageOperation
  20. {
  21. internal override void Start()
  22. {
  23. Status = EOperationStatus.Succeed;
  24. }
  25. internal override void Update()
  26. {
  27. }
  28. /// <summary>
  29. /// 创建包裹下载器
  30. /// </summary>
  31. public override PackageDownloaderOperation CreatePackageDownloader(int downloadingMaxNumber, int failedTryAgain)
  32. {
  33. List<BundleInfo> downloadList = new List<BundleInfo>();
  34. var operation = new PackageDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
  35. return operation;
  36. }
  37. }
  38. /// <summary>
  39. /// 离线模式的更新资源包裹操作
  40. /// </summary>
  41. internal sealed class OfflinePlayModeUpdatePackageOperation : UpdatePackageOperation
  42. {
  43. internal override void Start()
  44. {
  45. Status = EOperationStatus.Succeed;
  46. }
  47. internal override void Update()
  48. {
  49. }
  50. /// <summary>
  51. /// 创建包裹下载器
  52. /// </summary>
  53. public override PackageDownloaderOperation CreatePackageDownloader(int downloadingMaxNumber, int failedTryAgain)
  54. {
  55. List<BundleInfo> downloadList = new List<BundleInfo>();
  56. var operation = new PackageDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
  57. return operation;
  58. }
  59. }
  60. /// <summary>
  61. /// 联机模式的更新资源包裹操作
  62. /// </summary>
  63. internal sealed class HostPlayModeUpdatePackageOperation : UpdatePackageOperation
  64. {
  65. private enum ESteps
  66. {
  67. None,
  68. LoadWebManifest,
  69. CheckWebManifest,
  70. Done,
  71. }
  72. private static int RequestCount = 0;
  73. private readonly HostPlayModeImpl _impl;
  74. private readonly int _resourceVersion;
  75. private readonly int _timeout;
  76. private ESteps _steps = ESteps.None;
  77. private UnityWebDataRequester _downloader;
  78. private PatchManifest _remotePatchManifest;
  79. internal HostPlayModeUpdatePackageOperation(HostPlayModeImpl impl, int resourceVersion, int timeout)
  80. {
  81. _impl = impl;
  82. _resourceVersion = resourceVersion;
  83. _timeout = timeout;
  84. }
  85. internal override void Start()
  86. {
  87. RequestCount++;
  88. _steps = ESteps.LoadWebManifest;
  89. }
  90. internal override void Update()
  91. {
  92. if (_steps == ESteps.None || _steps == ESteps.Done)
  93. return;
  94. if (_steps == ESteps.LoadWebManifest)
  95. {
  96. string webURL = GetPatchManifestRequestURL(YooAssetSettingsData.GetPatchManifestFileName(_resourceVersion));
  97. YooLogger.Log($"Beginning to request patch manifest : {webURL}");
  98. _downloader = new UnityWebDataRequester();
  99. _downloader.SendRequest(webURL, _timeout);
  100. _steps = ESteps.CheckWebManifest;
  101. }
  102. if (_steps == ESteps.CheckWebManifest)
  103. {
  104. Progress = _downloader.Progress();
  105. if (_downloader.IsDone() == false)
  106. return;
  107. // Check error
  108. if (_downloader.HasError())
  109. {
  110. _steps = ESteps.Done;
  111. Status = EOperationStatus.Failed;
  112. Error = _downloader.GetError();
  113. }
  114. else
  115. {
  116. // 解析补丁清单
  117. if (ParseRemotePatchManifest(_downloader.GetText()))
  118. {
  119. _steps = ESteps.Done;
  120. Status = EOperationStatus.Succeed;
  121. }
  122. else
  123. {
  124. _steps = ESteps.Done;
  125. Status = EOperationStatus.Failed;
  126. Error = $"URL : {_downloader.URL} Error : remote patch manifest content is invalid";
  127. }
  128. }
  129. _downloader.Dispose();
  130. }
  131. }
  132. /// <summary>
  133. /// 创建包裹下载器
  134. /// </summary>
  135. public override PackageDownloaderOperation CreatePackageDownloader(int downloadingMaxNumber, int failedTryAgain)
  136. {
  137. if (Status == EOperationStatus.Succeed)
  138. {
  139. List<BundleInfo> downloadList = GetDownloadList();
  140. var operation = new PackageDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain);
  141. return operation;
  142. }
  143. else
  144. {
  145. YooLogger.Error($"{nameof(UpdatePackageOperation)} status is failed !");
  146. var operation = new PackageDownloaderOperation(null, downloadingMaxNumber, failedTryAgain);
  147. return operation;
  148. }
  149. }
  150. /// <summary>
  151. /// 获取补丁清单请求地址
  152. /// </summary>
  153. private string GetPatchManifestRequestURL(string fileName)
  154. {
  155. // 轮流返回请求地址
  156. if (RequestCount % 2 == 0)
  157. return _impl.GetPatchDownloadFallbackURL(fileName);
  158. else
  159. return _impl.GetPatchDownloadMainURL(fileName);
  160. }
  161. /// <summary>
  162. /// 解析远端请求的补丁清单
  163. /// </summary>
  164. private bool ParseRemotePatchManifest(string content)
  165. {
  166. try
  167. {
  168. _remotePatchManifest = PatchManifest.Deserialize(content);
  169. return true;
  170. }
  171. catch (Exception e)
  172. {
  173. YooLogger.Warning(e.ToString());
  174. return false;
  175. }
  176. }
  177. /// <summary>
  178. /// 获取下载列表
  179. /// </summary>
  180. private List<BundleInfo> GetDownloadList()
  181. {
  182. List<PatchBundle> downloadList = new List<PatchBundle>(1000);
  183. foreach (var patchBundle in _remotePatchManifest.BundleList)
  184. {
  185. // 忽略缓存文件
  186. if (CacheSystem.IsCached(patchBundle))
  187. continue;
  188. // 忽略APP资源
  189. // 注意:如果是APP资源并且哈希值相同,则不需要下载
  190. if (_impl.AppPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
  191. {
  192. if (appPatchBundle.IsBuildin && appPatchBundle.Equals(patchBundle))
  193. continue;
  194. }
  195. downloadList.Add(patchBundle);
  196. }
  197. return _impl.ConvertToDownloadList(downloadList);
  198. }
  199. }
  200. }