PatchManifest.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. namespace YooAsset
  7. {
  8. /// <summary>
  9. /// 补丁清单文件
  10. /// </summary>
  11. [Serializable]
  12. internal class PatchManifest
  13. {
  14. /// <summary>
  15. /// 文件版本
  16. /// </summary>
  17. public string FileVersion;
  18. /// <summary>
  19. /// 资源版本号
  20. /// </summary>
  21. public int ResourceVersion;
  22. /// <summary>
  23. /// 启用可寻址资源定位
  24. /// </summary>
  25. public bool EnableAddressable;
  26. /// <summary>
  27. /// 文件名称样式
  28. /// </summary>
  29. public int OutputNameStyle;
  30. /// <summary>
  31. /// 内置资源的标签列表(首包资源)
  32. /// </summary>
  33. public string BuildinTags;
  34. /// <summary>
  35. /// 资源列表(主动收集的资源列表)
  36. /// </summary>
  37. public List<PatchAsset> AssetList = new List<PatchAsset>();
  38. /// <summary>
  39. /// 资源包列表
  40. /// </summary>
  41. public List<PatchBundle> BundleList = new List<PatchBundle>();
  42. /// <summary>
  43. /// 资源包集合(提供BundleName获取PatchBundle)
  44. /// </summary>
  45. [NonSerialized]
  46. public readonly Dictionary<string, PatchBundle> BundleDic = new Dictionary<string, PatchBundle>();
  47. /// <summary>
  48. /// 资源映射集合(提供AssetPath获取PatchAsset)
  49. /// </summary>
  50. [NonSerialized]
  51. public readonly Dictionary<string, PatchAsset> AssetDic = new Dictionary<string, PatchAsset>();
  52. /// <summary>
  53. /// 资源路径映射集合
  54. /// </summary>
  55. [NonSerialized]
  56. public readonly Dictionary<string, string> AssetPathMapping = new Dictionary<string, string>();
  57. // 资源路径映射相关
  58. private bool _isInitAssetPathMapping = false;
  59. private bool _locationToLower = false;
  60. /// <summary>
  61. /// 初始化资源路径映射
  62. /// </summary>
  63. public void InitAssetPathMapping(bool locationToLower)
  64. {
  65. if (_isInitAssetPathMapping)
  66. return;
  67. _isInitAssetPathMapping = true;
  68. if (EnableAddressable)
  69. {
  70. if (locationToLower)
  71. YooLogger.Error("Addressable not support location to lower !");
  72. foreach (var patchAsset in AssetList)
  73. {
  74. string location = patchAsset.Address;
  75. if (AssetPathMapping.ContainsKey(location))
  76. throw new Exception($"Address have existed : {location}");
  77. else
  78. AssetPathMapping.Add(location, patchAsset.AssetPath);
  79. }
  80. }
  81. else
  82. {
  83. _locationToLower = locationToLower;
  84. foreach (var patchAsset in AssetList)
  85. {
  86. string location = patchAsset.AssetPath;
  87. if (locationToLower)
  88. location = location.ToLower();
  89. // 添加原生路径的映射
  90. if (AssetPathMapping.ContainsKey(location))
  91. throw new Exception($"AssetPath have existed : {location}");
  92. else
  93. AssetPathMapping.Add(location, patchAsset.AssetPath);
  94. // 添加无后缀名路径的映射
  95. if (Path.HasExtension(location))
  96. {
  97. string locationWithoutExtension = StringUtility.RemoveExtension(location);
  98. if (AssetPathMapping.ContainsKey(locationWithoutExtension))
  99. YooLogger.Warning($"AssetPath have existed : {locationWithoutExtension}");
  100. else
  101. AssetPathMapping.Add(locationWithoutExtension, patchAsset.AssetPath);
  102. }
  103. }
  104. }
  105. }
  106. /// <summary>
  107. /// 映射为资源路径
  108. /// </summary>
  109. public string MappingToAssetPath(string location)
  110. {
  111. if (string.IsNullOrEmpty(location))
  112. {
  113. YooLogger.Error("Failed to mapping location to asset path, The location is null or empty.");
  114. return string.Empty;
  115. }
  116. if (_locationToLower)
  117. location = location.ToLower();
  118. if (AssetPathMapping.TryGetValue(location, out string assetPath))
  119. {
  120. return assetPath;
  121. }
  122. else
  123. {
  124. YooLogger.Warning($"Failed to mapping location to asset path : {location}");
  125. return string.Empty;
  126. }
  127. }
  128. /// <summary>
  129. /// 获取主资源包
  130. /// 注意:传入的资源路径一定合法有效!
  131. /// </summary>
  132. public PatchBundle GetMainPatchBundle(string assetPath)
  133. {
  134. if (AssetDic.TryGetValue(assetPath, out PatchAsset patchAsset))
  135. {
  136. int bundleID = patchAsset.BundleID;
  137. if (bundleID >= 0 && bundleID < BundleList.Count)
  138. {
  139. var patchBundle = BundleList[bundleID];
  140. return patchBundle;
  141. }
  142. else
  143. {
  144. throw new Exception($"Invalid bundle id : {bundleID} Asset path : {assetPath}");
  145. }
  146. }
  147. else
  148. {
  149. throw new Exception("Should never get here !");
  150. }
  151. }
  152. /// <summary>
  153. /// 获取资源依赖列表
  154. /// 注意:传入的资源路径一定合法有效!
  155. /// </summary>
  156. public PatchBundle[] GetAllDependencies(string assetPath)
  157. {
  158. if (AssetDic.TryGetValue(assetPath, out PatchAsset patchAsset))
  159. {
  160. List<PatchBundle> result = new List<PatchBundle>(patchAsset.DependIDs.Length);
  161. foreach (var dependID in patchAsset.DependIDs)
  162. {
  163. if (dependID >= 0 && dependID < BundleList.Count)
  164. {
  165. var dependPatchBundle = BundleList[dependID];
  166. result.Add(dependPatchBundle);
  167. }
  168. else
  169. {
  170. throw new Exception($"Invalid bundle id : {dependID} Asset path : {assetPath}");
  171. }
  172. }
  173. return result.ToArray();
  174. }
  175. else
  176. {
  177. throw new Exception("Should never get here !");
  178. }
  179. }
  180. /// <summary>
  181. /// 尝试获取补丁资源
  182. /// </summary>
  183. public bool TryGetPatchAsset(string assetPath, out PatchAsset result)
  184. {
  185. return AssetDic.TryGetValue(assetPath, out result);
  186. }
  187. /// <summary>
  188. /// 尝试获取补丁资源包
  189. /// </summary>
  190. public bool TryGetPatchBundle(string bundleName, out PatchBundle result)
  191. {
  192. return BundleDic.TryGetValue(bundleName, out result);
  193. }
  194. /// <summary>
  195. /// 序列化
  196. /// </summary>
  197. public static void Serialize(string savePath, PatchManifest patchManifest)
  198. {
  199. string json = JsonUtility.ToJson(patchManifest);
  200. FileUtility.CreateFile(savePath, json);
  201. }
  202. /// <summary>
  203. /// 反序列化
  204. /// </summary>
  205. public static PatchManifest Deserialize(string jsonData)
  206. {
  207. PatchManifest patchManifest = JsonUtility.FromJson<PatchManifest>(jsonData);
  208. // 检测文件版本
  209. if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion)
  210. throw new Exception($"The manifest file version are not compatible : {patchManifest.FileVersion} != {YooAssetSettings.PatchManifestFileVersion}");
  211. // BundleList
  212. foreach (var patchBundle in patchManifest.BundleList)
  213. {
  214. patchBundle.ParseFlagsValue();
  215. patchBundle.ParseFileName(patchManifest.OutputNameStyle);
  216. patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle);
  217. }
  218. // AssetList
  219. foreach (var patchAsset in patchManifest.AssetList)
  220. {
  221. // 注意:我们不允许原始路径存在重名
  222. string assetPath = patchAsset.AssetPath;
  223. if (patchManifest.AssetDic.ContainsKey(assetPath))
  224. throw new Exception($"AssetPath have existed : {assetPath}");
  225. else
  226. patchManifest.AssetDic.Add(assetPath, patchAsset);
  227. }
  228. return patchManifest;
  229. }
  230. }
  231. }