using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
///
/// 补丁清单文件
///
[Serializable]
internal class PatchManifest
{
///
/// 文件版本
///
public string FileVersion;
///
/// 启用可寻址资源定位
///
public bool EnableAddressable;
///
/// 文件名称样式
///
public int OutputNameStyle;
///
/// 资源包裹名称
///
public string PackageName;
///
/// 资源列表(主动收集的资源列表)
///
public List AssetList = new List();
///
/// 资源包列表
///
public List BundleList = new List();
///
/// 资源包集合(提供BundleName获取PatchBundle)
///
[NonSerialized]
public readonly Dictionary BundleDic = new Dictionary();
///
/// 资源映射集合(提供AssetPath获取PatchAsset)
///
[NonSerialized]
public readonly Dictionary AssetDic = new Dictionary();
///
/// 资源路径映射集合
///
[NonSerialized]
public readonly Dictionary AssetPathMapping = new Dictionary();
// 资源路径映射相关
private bool _isInitAssetPathMapping = false;
private bool _locationToLower = false;
///
/// 初始化资源路径映射
///
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);
}
}
}
}
///
/// 映射为资源路径
///
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;
}
}
///
/// 获取主资源包
/// 注意:传入的资源路径一定合法有效!
///
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 !");
}
}
///
/// 获取资源依赖列表
/// 注意:传入的资源路径一定合法有效!
///
public PatchBundle[] GetAllDependencies(string assetPath)
{
if (AssetDic.TryGetValue(assetPath, out PatchAsset patchAsset))
{
List result = new List(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 !");
}
}
///
/// 尝试获取补丁资源
///
public bool TryGetPatchAsset(string assetPath, out PatchAsset result)
{
return AssetDic.TryGetValue(assetPath, out result);
}
///
/// 尝试获取补丁资源包
///
public bool TryGetPatchBundle(string bundleName, out PatchBundle result)
{
return BundleDic.TryGetValue(bundleName, out result);
}
///
/// 序列化
///
public static void Serialize(string savePath, PatchManifest patchManifest)
{
string json = JsonUtility.ToJson(patchManifest);
FileUtility.CreateFile(savePath, json);
}
///
/// 反序列化
///
public static PatchManifest Deserialize(string jsonData)
{
PatchManifest patchManifest = JsonUtility.FromJson(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;
}
}
}