DefaultBuildinFileSystem.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace YooAsset
  6. {
  7. /// <summary>
  8. /// 内置文件系统
  9. /// </summary>
  10. internal class DefaultBuildinFileSystem : IFileSystem
  11. {
  12. public class FileWrapper
  13. {
  14. public string FileName { private set; get; }
  15. public FileWrapper(string fileName)
  16. {
  17. FileName = fileName;
  18. }
  19. }
  20. protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
  21. protected readonly Dictionary<string, string> _buildinFilePathMapping = new Dictionary<string, string>(10000);
  22. protected IFileSystem _unpackFileSystem;
  23. protected string _packageRoot;
  24. /// <summary>
  25. /// 包裹名称
  26. /// </summary>
  27. public string PackageName { private set; get; }
  28. /// <summary>
  29. /// 文件根目录
  30. /// </summary>
  31. public string FileRoot
  32. {
  33. get
  34. {
  35. return _packageRoot;
  36. }
  37. }
  38. /// <summary>
  39. /// 文件数量
  40. /// </summary>
  41. public int FileCount
  42. {
  43. get
  44. {
  45. return _wrappers.Count;
  46. }
  47. }
  48. #region 自定义参数
  49. /// <summary>
  50. /// 自定义参数:初始化的时候缓存文件校验级别
  51. /// </summary>
  52. public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
  53. /// <summary>
  54. /// 自定义参数:数据文件追加文件格式
  55. /// </summary>
  56. public bool AppendFileExtension { private set; get; } = false;
  57. /// <summary>
  58. /// 自定义参数:禁用Catalog目录查询文件
  59. /// </summary>
  60. public bool DisableCatalogFile { private set; get; } = false;
  61. /// <summary>
  62. /// 自定义参数:拷贝内置清单
  63. /// </summary>
  64. public bool CopyBuildinPackageManifest { private set; get; } = false;
  65. /// <summary>
  66. /// 自定义参数:拷贝内置清单的目标目录
  67. /// 注意:该参数为空的时候,会获取默认的沙盒目录!
  68. /// </summary>
  69. public string CopyBuildinPackageManifestDestRoot { private set; get; }
  70. /// <summary>
  71. /// 自定义参数:解密方法类
  72. /// </summary>
  73. public IDecryptionServices DecryptionServices { private set; get; }
  74. #endregion
  75. public DefaultBuildinFileSystem()
  76. {
  77. }
  78. public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
  79. {
  80. var operation = new DBFSInitializeOperation(this);
  81. return operation;
  82. }
  83. public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
  84. {
  85. var operation = new DBFSLoadPackageManifestOperation(this, packageVersion);
  86. return operation;
  87. }
  88. public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
  89. {
  90. var operation = new DBFSRequestPackageVersionOperation(this);
  91. return operation;
  92. }
  93. public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
  94. {
  95. return _unpackFileSystem.ClearCacheFilesAsync(manifest, clearMode, clearParam);
  96. }
  97. public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadParam param)
  98. {
  99. // 注意:业务层的解压下载器会依赖内置文件系统的下载方法
  100. param.ImportFilePath = GetBuildinFileLoadPath(bundle);
  101. return _unpackFileSystem.DownloadFileAsync(bundle, param);
  102. }
  103. public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
  104. {
  105. if (IsUnpackBundleFile(bundle))
  106. {
  107. return _unpackFileSystem.LoadBundleFile(bundle);
  108. }
  109. if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
  110. {
  111. var operation = new DBFSLoadAssetBundleOperation(this, bundle);
  112. return operation;
  113. }
  114. else if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
  115. {
  116. var operation = new DBFSLoadRawBundleOperation(this, bundle);
  117. return operation;
  118. }
  119. else
  120. {
  121. string error = $"{nameof(DefaultBuildinFileSystem)} not support load bundle type : {bundle.BundleType}";
  122. var operation = new FSLoadBundleCompleteOperation(error);
  123. return operation;
  124. }
  125. }
  126. public virtual void SetParameter(string name, object value)
  127. {
  128. if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
  129. {
  130. FileVerifyLevel = (EFileVerifyLevel)value;
  131. }
  132. else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
  133. {
  134. AppendFileExtension = Convert.ToBoolean(value);
  135. }
  136. else if (name == FileSystemParametersDefine.DISABLE_CATALOG_FILE)
  137. {
  138. DisableCatalogFile = Convert.ToBoolean(value);
  139. }
  140. else if (name == FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST)
  141. {
  142. CopyBuildinPackageManifest = Convert.ToBoolean(value);
  143. }
  144. else if (name == FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST_DEST_ROOT)
  145. {
  146. CopyBuildinPackageManifestDestRoot = (string)value;
  147. }
  148. else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
  149. {
  150. DecryptionServices = (IDecryptionServices)value;
  151. }
  152. else
  153. {
  154. YooLogger.Warning($"Invalid parameter : {name}");
  155. }
  156. }
  157. public virtual void OnCreate(string packageName, string packageRoot)
  158. {
  159. PackageName = packageName;
  160. if (string.IsNullOrEmpty(packageRoot))
  161. _packageRoot = GetDefaultBuildinPackageRoot(packageName);
  162. else
  163. _packageRoot = packageRoot;
  164. // 创建解压文件系统
  165. var remoteServices = new DefaultUnpackRemoteServices(_packageRoot);
  166. _unpackFileSystem = new DefaultUnpackFileSystem();
  167. _unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
  168. _unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
  169. _unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
  170. _unpackFileSystem.SetParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, DecryptionServices);
  171. _unpackFileSystem.OnCreate(packageName, null);
  172. }
  173. public virtual void OnDestroy()
  174. {
  175. }
  176. public virtual bool Belong(PackageBundle bundle)
  177. {
  178. if (DisableCatalogFile)
  179. return true;
  180. return _wrappers.ContainsKey(bundle.BundleGUID);
  181. }
  182. public virtual bool Exists(PackageBundle bundle)
  183. {
  184. if (DisableCatalogFile)
  185. return true;
  186. return _wrappers.ContainsKey(bundle.BundleGUID);
  187. }
  188. public virtual bool NeedDownload(PackageBundle bundle)
  189. {
  190. return false;
  191. }
  192. public virtual bool NeedUnpack(PackageBundle bundle)
  193. {
  194. if (IsUnpackBundleFile(bundle))
  195. {
  196. return _unpackFileSystem.Exists(bundle) == false;
  197. }
  198. else
  199. {
  200. return false;
  201. }
  202. }
  203. public virtual bool NeedImport(PackageBundle bundle)
  204. {
  205. return false;
  206. }
  207. public virtual string GetBundleFilePath(PackageBundle bundle)
  208. {
  209. if (IsUnpackBundleFile(bundle))
  210. return _unpackFileSystem.GetBundleFilePath(bundle);
  211. return GetBuildinFileLoadPath(bundle);
  212. }
  213. public virtual byte[] ReadBundleFileData(PackageBundle bundle)
  214. {
  215. if (IsUnpackBundleFile(bundle))
  216. return _unpackFileSystem.ReadBundleFileData(bundle);
  217. if (Exists(bundle) == false)
  218. return null;
  219. #if UNITY_ANDROID
  220. //TODO : 安卓平台内置文件属于APK压缩包内的文件。
  221. YooLogger.Error($"Android platform not support read buildin bundle file data !");
  222. return null;
  223. #else
  224. if (bundle.Encrypted)
  225. {
  226. if (DecryptionServices == null)
  227. {
  228. YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
  229. return null;
  230. }
  231. string filePath = GetBuildinFileLoadPath(bundle);
  232. var fileInfo = new DecryptFileInfo()
  233. {
  234. BundleName = bundle.BundleName,
  235. FileLoadCRC = bundle.UnityCRC,
  236. FileLoadPath = filePath,
  237. };
  238. return DecryptionServices.ReadFileData(fileInfo);
  239. }
  240. else
  241. {
  242. string filePath = GetBuildinFileLoadPath(bundle);
  243. return FileUtility.ReadAllBytes(filePath);
  244. }
  245. #endif
  246. }
  247. public virtual string ReadBundleFileText(PackageBundle bundle)
  248. {
  249. if (IsUnpackBundleFile(bundle))
  250. return _unpackFileSystem.ReadBundleFileText(bundle);
  251. if (Exists(bundle) == false)
  252. return null;
  253. #if UNITY_ANDROID
  254. //TODO : 安卓平台内置文件属于APK压缩包内的文件。
  255. YooLogger.Error($"Android platform not support read buildin bundle file text !");
  256. return null;
  257. #else
  258. if (bundle.Encrypted)
  259. {
  260. if (DecryptionServices == null)
  261. {
  262. YooLogger.Error($"The {nameof(IDecryptionServices)} is null !");
  263. return null;
  264. }
  265. string filePath = GetBuildinFileLoadPath(bundle);
  266. var fileInfo = new DecryptFileInfo()
  267. {
  268. BundleName = bundle.BundleName,
  269. FileLoadCRC = bundle.UnityCRC,
  270. FileLoadPath = filePath,
  271. };
  272. return DecryptionServices.ReadFileText(fileInfo);
  273. }
  274. else
  275. {
  276. string filePath = GetBuildinFileLoadPath(bundle);
  277. return FileUtility.ReadAllText(filePath);
  278. }
  279. #endif
  280. }
  281. #region 内部方法
  282. protected string GetDefaultBuildinPackageRoot(string packageName)
  283. {
  284. string rootDirectory = YooAssetSettingsData.GetYooDefaultBuildinRoot();
  285. return PathUtility.Combine(rootDirectory, packageName);
  286. }
  287. public string GetBuildinFileLoadPath(PackageBundle bundle)
  288. {
  289. if (_buildinFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
  290. {
  291. filePath = PathUtility.Combine(_packageRoot, bundle.FileName);
  292. _buildinFilePathMapping.Add(bundle.BundleGUID, filePath);
  293. }
  294. return filePath;
  295. }
  296. public string GetBuildinPackageVersionFilePath()
  297. {
  298. string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
  299. return PathUtility.Combine(_packageRoot, fileName);
  300. }
  301. public string GetBuildinPackageHashFilePath(string packageVersion)
  302. {
  303. string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
  304. return PathUtility.Combine(_packageRoot, fileName);
  305. }
  306. public string GetBuildinPackageManifestFilePath(string packageVersion)
  307. {
  308. string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
  309. return PathUtility.Combine(_packageRoot, fileName);
  310. }
  311. public string GetCatalogBinaryFileLoadPath()
  312. {
  313. return PathUtility.Combine(_packageRoot, DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName);
  314. }
  315. /// <summary>
  316. /// 是否属于解压资源包文件
  317. /// </summary>
  318. protected bool IsUnpackBundleFile(PackageBundle bundle)
  319. {
  320. if (Belong(bundle) == false)
  321. return false;
  322. #if UNITY_ANDROID
  323. if (bundle.Encrypted)
  324. return true;
  325. if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
  326. return true;
  327. return false;
  328. #else
  329. return false;
  330. #endif
  331. }
  332. /// <summary>
  333. /// 记录文件信息
  334. /// </summary>
  335. public bool RecordCatalogFile(string bundleGUID, FileWrapper wrapper)
  336. {
  337. if (_wrappers.ContainsKey(bundleGUID))
  338. {
  339. YooLogger.Error($"{nameof(DefaultBuildinFileSystem)} has element : {bundleGUID}");
  340. return false;
  341. }
  342. _wrappers.Add(bundleGUID, wrapper);
  343. return true;
  344. }
  345. /// <summary>
  346. /// 初始化解压文件系统
  347. /// </summary>
  348. public FSInitializeFileSystemOperation InitializeUpackFileSystem()
  349. {
  350. return _unpackFileSystem.InitializeFileSystemAsync();
  351. }
  352. /// <summary>
  353. /// 加载加密的资源文件
  354. /// </summary>
  355. public DecryptResult LoadEncryptedAssetBundle(PackageBundle bundle)
  356. {
  357. string filePath = GetBuildinFileLoadPath(bundle);
  358. var fileInfo = new DecryptFileInfo()
  359. {
  360. BundleName = bundle.BundleName,
  361. FileLoadCRC = bundle.UnityCRC,
  362. FileLoadPath = filePath,
  363. };
  364. return DecryptionServices.LoadAssetBundle(fileInfo);
  365. }
  366. /// <summary>
  367. /// 加载加密的资源文件
  368. /// </summary>
  369. public DecryptResult LoadEncryptedAssetBundleAsync(PackageBundle bundle)
  370. {
  371. string filePath = GetBuildinFileLoadPath(bundle);
  372. var fileInfo = new DecryptFileInfo()
  373. {
  374. BundleName = bundle.BundleName,
  375. FileLoadCRC = bundle.UnityCRC,
  376. FileLoadPath = filePath,
  377. };
  378. return DecryptionServices.LoadAssetBundleAsync(fileInfo);
  379. }
  380. #endregion
  381. }
  382. }