RawFileOperation.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. using System.IO;
  2. namespace YooAsset
  3. {
  4. /// <summary>
  5. /// 原生文件操作
  6. /// </summary>
  7. public abstract class RawFileOperation : AsyncOperationBase
  8. {
  9. internal readonly BundleInfo _bundleInfo;
  10. /// <summary>
  11. /// 原生文件的拷贝路径
  12. /// </summary>
  13. public string CopyPath { private set; get; }
  14. internal RawFileOperation(BundleInfo bundleInfo, string copyPath)
  15. {
  16. _bundleInfo = bundleInfo;
  17. CopyPath = copyPath;
  18. }
  19. /// <summary>
  20. /// 原生文件的缓存路径
  21. /// </summary>
  22. public abstract string GetCachePath();
  23. /// <summary>
  24. /// 获取原生文件的二进制数据
  25. /// </summary>
  26. public byte[] LoadFileData()
  27. {
  28. string filePath = GetCachePath();
  29. if (File.Exists(filePath) == false)
  30. return null;
  31. return File.ReadAllBytes(filePath);
  32. }
  33. /// <summary>
  34. /// 获取原生文件的文本数据
  35. /// </summary>
  36. public string LoadFileText()
  37. {
  38. string filePath = GetCachePath();
  39. if (File.Exists(filePath) == false)
  40. return string.Empty;
  41. return File.ReadAllText(filePath, System.Text.Encoding.UTF8);
  42. }
  43. }
  44. /// <summary>
  45. /// 发生错误的原生文件操作
  46. /// </summary>
  47. internal sealed class CompletedRawFileOperation : RawFileOperation
  48. {
  49. private readonly string _error;
  50. internal CompletedRawFileOperation(string error, string copyPath) : base(null, copyPath)
  51. {
  52. _error = error;
  53. }
  54. internal override void Start()
  55. {
  56. Status = EOperationStatus.Failed;
  57. Error = _error;
  58. }
  59. internal override void Update()
  60. {
  61. }
  62. /// <summary>
  63. /// 原生文件的缓存路径
  64. /// </summary>
  65. public override string GetCachePath()
  66. {
  67. return string.Empty;
  68. }
  69. }
  70. /// <summary>
  71. /// 编辑器下模拟运行的原生文件操作
  72. /// </summary>
  73. internal sealed class EditorPlayModeRawFileOperation : RawFileOperation
  74. {
  75. private enum ESteps
  76. {
  77. None,
  78. Prepare,
  79. CheckAndCopyFile,
  80. Done,
  81. }
  82. private ESteps _steps = ESteps.None;
  83. internal EditorPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
  84. {
  85. }
  86. internal override void Start()
  87. {
  88. _steps = ESteps.Prepare;
  89. }
  90. internal override void Update()
  91. {
  92. if (_steps == ESteps.None || _steps == ESteps.Done)
  93. return;
  94. // 1. 准备工作
  95. if (_steps == ESteps.Prepare)
  96. {
  97. if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromEditor)
  98. {
  99. _steps = ESteps.CheckAndCopyFile;
  100. return; // 模拟实现异步操作
  101. }
  102. else
  103. {
  104. throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
  105. }
  106. }
  107. // 2. 检测并拷贝原生文件
  108. if (_steps == ESteps.CheckAndCopyFile)
  109. {
  110. // 如果不需要保存文件
  111. if (string.IsNullOrEmpty(CopyPath))
  112. {
  113. _steps = ESteps.Done;
  114. Status = EOperationStatus.Succeed;
  115. return;
  116. }
  117. // 如果原生文件已经存在,则将其删除
  118. if (File.Exists(CopyPath))
  119. {
  120. File.Delete(CopyPath);
  121. }
  122. try
  123. {
  124. FileUtility.CreateFileDirectory(CopyPath);
  125. File.Copy(GetCachePath(), CopyPath, true);
  126. _steps = ESteps.Done;
  127. Status = EOperationStatus.Succeed;
  128. }
  129. catch (System.Exception e)
  130. {
  131. _steps = ESteps.Done;
  132. Status = EOperationStatus.Failed;
  133. Error = e.ToString();
  134. }
  135. }
  136. }
  137. /// <summary>
  138. /// 原生文件的缓存路径
  139. /// </summary>
  140. public override string GetCachePath()
  141. {
  142. if (_bundleInfo == null)
  143. return string.Empty;
  144. return _bundleInfo.EditorAssetPath;
  145. }
  146. }
  147. /// <summary>
  148. /// 离线模式的原生文件操作
  149. /// </summary>
  150. internal sealed class OfflinePlayModeRawFileOperation : RawFileOperation
  151. {
  152. private enum ESteps
  153. {
  154. None,
  155. Prepare,
  156. DownloadBuildinFile,
  157. CheckDownload,
  158. CheckAndCopyFile,
  159. Done,
  160. }
  161. private ESteps _steps = ESteps.None;
  162. private DownloaderBase _downloader;
  163. public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
  164. {
  165. }
  166. internal override void Start()
  167. {
  168. _steps = ESteps.Prepare;
  169. }
  170. internal override void Update()
  171. {
  172. if (_steps == ESteps.None || _steps == ESteps.Done)
  173. return;
  174. // 1. 准备工作
  175. if (_steps == ESteps.Prepare)
  176. {
  177. if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.None)
  178. {
  179. _steps = ESteps.Done;
  180. Status = EOperationStatus.Failed;
  181. Error = $"Bundle info is invalid : {_bundleInfo.Bundle.BundleName}";
  182. }
  183. else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
  184. {
  185. _steps = ESteps.DownloadBuildinFile;
  186. }
  187. else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
  188. {
  189. _steps = ESteps.CheckAndCopyFile;
  190. }
  191. else
  192. {
  193. throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
  194. }
  195. }
  196. // 2. 下载文件
  197. if (_steps == ESteps.DownloadBuildinFile)
  198. {
  199. int failedTryAgain = int.MaxValue;
  200. var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
  201. _downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
  202. _steps = ESteps.CheckDownload;
  203. }
  204. // 3. 检测下载结果
  205. if (_steps == ESteps.CheckDownload)
  206. {
  207. Progress = _downloader.DownloadProgress;
  208. if (_downloader.IsDone() == false)
  209. return;
  210. if (_downloader.HasError())
  211. {
  212. _steps = ESteps.Done;
  213. Status = EOperationStatus.Failed;
  214. Error = _downloader.GetLastError();
  215. }
  216. else
  217. {
  218. _steps = ESteps.CheckAndCopyFile;
  219. }
  220. }
  221. // 4. 检测并拷贝原生文件
  222. if (_steps == ESteps.CheckAndCopyFile)
  223. {
  224. // 如果不需要保存文件
  225. if (string.IsNullOrEmpty(CopyPath))
  226. {
  227. _steps = ESteps.Done;
  228. Status = EOperationStatus.Succeed;
  229. return;
  230. }
  231. // 如果原生文件已经存在,则验证其完整性
  232. if (File.Exists(CopyPath))
  233. {
  234. var verifyResult = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
  235. if (verifyResult == EVerifyResult.Succeed)
  236. {
  237. _steps = ESteps.Done;
  238. Status = EOperationStatus.Succeed;
  239. return;
  240. }
  241. else
  242. {
  243. File.Delete(CopyPath);
  244. }
  245. }
  246. try
  247. {
  248. FileUtility.CreateFileDirectory(CopyPath);
  249. File.Copy(GetCachePath(), CopyPath, true);
  250. _steps = ESteps.Done;
  251. Status = EOperationStatus.Succeed;
  252. }
  253. catch (System.Exception e)
  254. {
  255. _steps = ESteps.Done;
  256. Status = EOperationStatus.Failed;
  257. Error = e.ToString();
  258. }
  259. }
  260. }
  261. /// <summary>
  262. /// 原生文件的缓存路径
  263. /// </summary>
  264. public override string GetCachePath()
  265. {
  266. if (_bundleInfo == null)
  267. return string.Empty;
  268. return _bundleInfo.Bundle.CachedFilePath;
  269. }
  270. }
  271. /// <summary>
  272. /// 联机模式的原生文件操作
  273. /// </summary>
  274. internal sealed class HostPlayModeRawFileOperation : RawFileOperation
  275. {
  276. private enum ESteps
  277. {
  278. None,
  279. Prepare,
  280. DownloadWebFile,
  281. DownloadBuildinFile,
  282. CheckDownload,
  283. CheckAndCopyFile,
  284. Done,
  285. }
  286. private ESteps _steps = ESteps.None;
  287. private DownloaderBase _downloader;
  288. internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
  289. {
  290. }
  291. internal override void Start()
  292. {
  293. _steps = ESteps.Prepare;
  294. }
  295. internal override void Update()
  296. {
  297. if (_steps == ESteps.None || _steps == ESteps.Done)
  298. return;
  299. // 1. 准备工作
  300. if (_steps == ESteps.Prepare)
  301. {
  302. if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.None)
  303. {
  304. _steps = ESteps.Done;
  305. Status = EOperationStatus.Failed;
  306. Error = $"Bundle info is invalid : {_bundleInfo.Bundle.BundleName}";
  307. }
  308. else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
  309. {
  310. _steps = ESteps.DownloadWebFile;
  311. }
  312. else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
  313. {
  314. _steps = ESteps.DownloadBuildinFile;
  315. }
  316. else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
  317. {
  318. _steps = ESteps.CheckAndCopyFile;
  319. }
  320. else
  321. {
  322. throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
  323. }
  324. }
  325. // 2. 下载远端文件
  326. if (_steps == ESteps.DownloadWebFile)
  327. {
  328. int failedTryAgain = int.MaxValue;
  329. _downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain);
  330. _steps = ESteps.CheckDownload;
  331. }
  332. // 3. 下载内置文件
  333. if (_steps == ESteps.DownloadBuildinFile)
  334. {
  335. int failedTryAgain = int.MaxValue;
  336. var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
  337. _downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
  338. _steps = ESteps.CheckDownload;
  339. }
  340. // 4. 检测下载结果
  341. if (_steps == ESteps.CheckDownload)
  342. {
  343. Progress = _downloader.DownloadProgress;
  344. if (_downloader.IsDone() == false)
  345. return;
  346. if (_downloader.HasError())
  347. {
  348. _steps = ESteps.Done;
  349. Status = EOperationStatus.Failed;
  350. Error = _downloader.GetLastError();
  351. }
  352. else
  353. {
  354. _steps = ESteps.CheckAndCopyFile;
  355. }
  356. }
  357. // 5. 检测并拷贝原生文件
  358. if (_steps == ESteps.CheckAndCopyFile)
  359. {
  360. // 如果不需要保存文件
  361. if (string.IsNullOrEmpty(CopyPath))
  362. {
  363. _steps = ESteps.Done;
  364. Status = EOperationStatus.Succeed;
  365. return;
  366. }
  367. // 如果原生文件已经存在,则验证其完整性
  368. if (File.Exists(CopyPath))
  369. {
  370. var verifyResult = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
  371. if (verifyResult == EVerifyResult.Succeed)
  372. {
  373. _steps = ESteps.Done;
  374. Status = EOperationStatus.Succeed;
  375. return;
  376. }
  377. else
  378. {
  379. File.Delete(CopyPath);
  380. }
  381. }
  382. try
  383. {
  384. FileUtility.CreateFileDirectory(CopyPath);
  385. File.Copy(GetCachePath(), CopyPath, true);
  386. _steps = ESteps.Done;
  387. Status = EOperationStatus.Succeed;
  388. }
  389. catch (System.Exception e)
  390. {
  391. _steps = ESteps.Done;
  392. Status = EOperationStatus.Failed;
  393. Error = e.ToString();
  394. }
  395. }
  396. }
  397. /// <summary>
  398. /// 原生文件的缓存路径
  399. /// </summary>
  400. public override string GetCachePath()
  401. {
  402. if (_bundleInfo == null)
  403. return string.Empty;
  404. return _bundleInfo.Bundle.CachedFilePath;
  405. }
  406. }
  407. }