YooAsset/Assets/YooAsset/Runtime/PatchSystem/PatchManifest.cs

258 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 补丁清单文件
/// </summary>
[Serializable]
internal class PatchManifest
{
/// <summary>
/// 文件版本
/// </summary>
public string FileVersion;
/// <summary>
/// 启用可寻址资源定位
/// </summary>
public bool EnableAddressable;
/// <summary>
/// 文件名称样式
/// </summary>
public int OutputNameStyle;
/// <summary>
/// 资源包裹名称
/// </summary>
public string PackageName;
/// <summary>
/// 资源列表(主动收集的资源列表)
/// </summary>
public List<PatchAsset> AssetList = new List<PatchAsset>();
/// <summary>
/// 资源包列表
/// </summary>
public List<PatchBundle> BundleList = new List<PatchBundle>();
/// <summary>
/// 资源包集合提供BundleName获取PatchBundle
/// </summary>
[NonSerialized]
public readonly Dictionary<string, PatchBundle> BundleDic = new Dictionary<string, PatchBundle>();
/// <summary>
/// 资源映射集合提供AssetPath获取PatchAsset
/// </summary>
[NonSerialized]
public readonly Dictionary<string, PatchAsset> AssetDic = new Dictionary<string, PatchAsset>();
/// <summary>
/// 资源路径映射集合
/// </summary>
[NonSerialized]
public readonly Dictionary<string, string> AssetPathMapping = new Dictionary<string, string>();
// 资源路径映射相关
private bool _isInitAssetPathMapping = false;
private bool _locationToLower = false;
/// <summary>
/// 初始化资源路径映射
/// </summary>
public void InitAssetPathMapping(bool locationToLower)
{
if (_isInitAssetPathMapping)
return;
_isInitAssetPathMapping = true;
if (EnableAddressable)
{
if (locationToLower)
YooLogger.Error("Addressable not support location to lower !");
foreach (var patchAsset in AssetList)
{
string location = patchAsset.Address;
if (AssetPathMapping.ContainsKey(location))
throw new Exception($"Address have existed : {location}");
else
AssetPathMapping.Add(location, patchAsset.AssetPath);
}
}
else
{
_locationToLower = locationToLower;
foreach (var patchAsset in AssetList)
{
string location = patchAsset.AssetPath;
if (locationToLower)
location = location.ToLower();
// 添加原生路径的映射
if (AssetPathMapping.ContainsKey(location))
throw new Exception($"AssetPath have existed : {location}");
else
AssetPathMapping.Add(location, patchAsset.AssetPath);
// 添加无后缀名路径的映射
if (Path.HasExtension(location))
{
string locationWithoutExtension = StringUtility.RemoveExtension(location);
if (AssetPathMapping.ContainsKey(locationWithoutExtension))
YooLogger.Warning($"AssetPath have existed : {locationWithoutExtension}");
else
AssetPathMapping.Add(locationWithoutExtension, patchAsset.AssetPath);
}
}
}
}
/// <summary>
/// 映射为资源路径
/// </summary>
public string MappingToAssetPath(string location)
{
if (string.IsNullOrEmpty(location))
{
YooLogger.Error("Failed to mapping location to asset path, The location is null or empty.");
return string.Empty;
}
if (_locationToLower)
location = location.ToLower();
if (AssetPathMapping.TryGetValue(location, out string assetPath))
{
return assetPath;
}
else
{
YooLogger.Warning($"Failed to mapping location to asset path : {location}");
return string.Empty;
}
}
/// <summary>
/// 获取主资源包
/// 注意:传入的资源路径一定合法有效!
/// </summary>
public PatchBundle GetMainPatchBundle(string assetPath)
{
if (AssetDic.TryGetValue(assetPath, out PatchAsset patchAsset))
{
int bundleID = patchAsset.BundleID;
if (bundleID >= 0 && bundleID < BundleList.Count)
{
var patchBundle = BundleList[bundleID];
return patchBundle;
}
else
{
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {assetPath}");
}
}
else
{
throw new Exception("Should never get here !");
}
}
/// <summary>
/// 获取资源依赖列表
/// 注意:传入的资源路径一定合法有效!
/// </summary>
public PatchBundle[] GetAllDependencies(string assetPath)
{
if (AssetDic.TryGetValue(assetPath, out PatchAsset patchAsset))
{
List<PatchBundle> result = new List<PatchBundle>(patchAsset.DependIDs.Length);
foreach (var dependID in patchAsset.DependIDs)
{
if (dependID >= 0 && dependID < BundleList.Count)
{
var dependPatchBundle = BundleList[dependID];
result.Add(dependPatchBundle);
}
else
{
throw new Exception($"Invalid bundle id : {dependID} Asset path : {assetPath}");
}
}
return result.ToArray();
}
else
{
throw new Exception("Should never get here !");
}
}
/// <summary>
/// 尝试获取补丁资源
/// </summary>
public bool TryGetPatchAsset(string assetPath, out PatchAsset result)
{
return AssetDic.TryGetValue(assetPath, out result);
}
/// <summary>
/// 尝试获取补丁资源包
/// </summary>
public bool TryGetPatchBundle(string bundleName, out PatchBundle result)
{
return BundleDic.TryGetValue(bundleName, out result);
}
/// <summary>
/// 序列化
/// </summary>
public static void Serialize(string savePath, PatchManifest patchManifest)
{
string json = JsonUtility.ToJson(patchManifest);
FileUtility.CreateFile(savePath, json);
}
/// <summary>
/// 反序列化
/// </summary>
public static PatchManifest Deserialize(string jsonData)
{
PatchManifest patchManifest = JsonUtility.FromJson<PatchManifest>(jsonData);
// 检测文件版本
if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion)
throw new Exception($"The manifest file version are not compatible : {patchManifest.FileVersion} != {YooAssetSettings.PatchManifestFileVersion}");
// BundleList
foreach (var patchBundle in patchManifest.BundleList)
{
patchBundle.ParseFlagsValue();
patchBundle.ParseFileName(patchManifest.OutputNameStyle);
patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle);
}
// AssetList
foreach (var patchAsset in patchManifest.AssetList)
{
// 注意:我们不允许原始路径存在重名
string assetPath = patchAsset.AssetPath;
if (patchManifest.AssetDic.ContainsKey(assetPath))
throw new Exception($"AssetPath have existed : {assetPath}");
else
patchManifest.AssetDic.Add(assetPath, patchAsset);
}
return patchManifest;
}
}
}