Files
YooAsset/Assets/YooAsset/Runtime/ResourcePackage/FileSystemHost.cs
2026-01-16 10:28:01 +08:00

435 lines
16 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
internal class FileSystemHost
{
public readonly string PackageName;
public readonly List<IFileSystem> FileSystems = new List<IFileSystem>(10);
/// <summary>
/// 当前激活的清单
/// </summary>
public PackageManifest ActiveManifest { set; get; }
public FileSystemHost(string packageName)
{
PackageName = packageName;
}
/// <summary>
/// 异步初始化
/// </summary>
public InitializeFileSystemOperation InitializeAsync(FileSystemParameters fileSystemParameter)
{
var fileSystemParamList = new List<FileSystemParameters>();
if (fileSystemParameter != null)
fileSystemParamList.Add(fileSystemParameter);
return InitializeAsync(fileSystemParamList);
}
/// <summary>
/// 异步初始化
/// </summary>
public InitializeFileSystemOperation InitializeAsync(FileSystemParameters fileSystemParameterA, FileSystemParameters fileSystemParameterB)
{
var fileSystemParamList = new List<FileSystemParameters>();
if (fileSystemParameterA != null)
fileSystemParamList.Add(fileSystemParameterA);
if (fileSystemParameterB != null)
fileSystemParamList.Add(fileSystemParameterB);
return InitializeAsync(fileSystemParamList);
}
/// <summary>
/// 异步初始化
/// </summary>
public InitializeFileSystemOperation InitializeAsync(List<FileSystemParameters> fileSystemParameterList)
{
var operation = new InitializeFileSystemOperation(this, fileSystemParameterList);
return operation;
}
/// <summary>
/// 销毁文件系统
/// </summary>
public void Destroy()
{
foreach (var fileSystem in FileSystems)
{
fileSystem.OnDestroy();
}
FileSystems.Clear();
}
#region
private BundleInfo CreateBundleInfo(PackageBundle packageBundle)
{
if (packageBundle == null)
throw new YooInternalException();
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem != null)
{
BundleInfo bundleInfo = new BundleInfo(fileSystem, packageBundle);
return bundleInfo;
}
throw new YooFileSystemException($"Can not found belong file system : {packageBundle.BundleName}");
}
/// <summary>
/// 获取主资源包信息
/// </summary>
public BundleInfo GetMainBundleInfo(AssetInfo assetInfo)
{
if (assetInfo == null || assetInfo.IsInvalid)
throw new YooInternalException();
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(assetInfo.Asset);
return CreateBundleInfo(packageBundle);
}
/// <summary>
/// 获取主资源包名称
/// </summary>
public string GetMainBundleName(int bundleID)
{
// 注意:如果清单里未找到资源包会抛出异常!
var packageBundle = ActiveManifest.GetMainPackageBundle(bundleID);
return packageBundle.BundleName;
}
/// <summary>
/// 获取依赖的资源包信息集合
/// </summary>
public List<BundleInfo> GetDependBundleInfos(AssetInfo assetInfo)
{
if (assetInfo == null || assetInfo.IsInvalid)
throw new YooInternalException();
// 注意:如果清单里未找到资源包会抛出异常!
List<PackageBundle> depends;
if (assetInfo.LoadMethod == AssetInfo.ELoadMethod.LoadAllAssets)
{
var mainBundle = ActiveManifest.GetMainPackageBundle(assetInfo.Asset);
depends = ActiveManifest.GetBundleAllDependencies(mainBundle);
}
else
{
depends = ActiveManifest.GetAssetAllDependencies(assetInfo.Asset);
}
List<BundleInfo> result = new List<BundleInfo>(depends.Count);
foreach (var packageBundle in depends)
{
BundleInfo bundleInfo = CreateBundleInfo(packageBundle);
result.Add(bundleInfo);
}
return result;
}
#endregion
#region
public ResourceDownloaderOperation CreateResourceDownloader(ResourceDownloaderOptions options)
{
List<BundleInfo> downloadList;
if (options.Tags == null)
downloadList = GetDownloadListByAll(ActiveManifest);
else
downloadList = GetDownloadListByTags(ActiveManifest, options.Tags);
var operation = new ResourceDownloaderOperation(PackageName, downloadList, options.MaximumConcurrency, options.FailedTryAgain);
return operation;
}
public ResourceDownloaderOperation CreateResourceDownloader(BundleDownloaderOptions options)
{
List<BundleInfo> downloadList;
if (options.AssetInfos == null)
downloadList = GetDownloadListByAll(ActiveManifest);
else
downloadList = GetDownloadListByAssetInfos(ActiveManifest, options.AssetInfos, options.DownloadBundleDependencies);
var operation = new ResourceDownloaderOperation(PackageName, downloadList, options.MaximumConcurrency, options.FailedTryAgain);
return operation;
}
public ResourceUnpackerOperation CreateResourceUnpacker(ResourceUnpackerOptions options)
{
List<BundleInfo> unpcakList;
if (options.Tags == null)
unpcakList = GetUnpackListByAll(ActiveManifest);
else
unpcakList = GetUnpackListByTags(ActiveManifest, options.Tags);
var operation = new ResourceUnpackerOperation(PackageName, unpcakList, options.MaximumConcurrency, options.FailedTryAgain);
return operation;
}
public ResourceImporterOperation CreateResourceImporter(BundleImporterOptions options)
{
List<BundleInfo> importerList = GetImporterListByBundleInfos(ActiveManifest, options.BundleInfos);
var operation = new ResourceImporterOperation(PackageName, importerList, options.MaximumConcurrency, options.FailedTryAgain);
return operation;
}
internal List<BundleInfo> GetDownloadListByAll(PackageManifest manifest)
{
if (manifest == null)
return new List<BundleInfo>();
List<BundleInfo> result = new List<BundleInfo>(1000);
foreach (var packageBundle in manifest.BundleList)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedDownload(packageBundle))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
}
return result;
}
internal List<BundleInfo> GetDownloadListByTags(PackageManifest manifest, string[] tags)
{
if (manifest == null)
return new List<BundleInfo>();
List<BundleInfo> result = new List<BundleInfo>(1000);
foreach (var packageBundle in manifest.BundleList)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedDownload(packageBundle))
{
// 如果未带任何标记,则统一下载
if (packageBundle.HasAnyTags() == false)
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
else
{
// 查询DLC资源
if (packageBundle.HasTag(tags))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
}
}
}
return result;
}
internal List<BundleInfo> GetDownloadListByAssetInfos(PackageManifest manifest, AssetInfo[] assetInfos, bool recursiveDownload)
{
if (manifest == null)
return new List<BundleInfo>();
// 获取资源对象的资源包和所有依赖资源包
HashSet<string> checkSet = new HashSet<string>();
List<PackageBundle> checkList = new List<PackageBundle>(assetInfos.Length);
foreach (var assetInfo in assetInfos)
{
if (assetInfo.IsInvalid)
{
YooLogger.Warning(assetInfo.Error);
continue;
}
// 注意:如果清单里未找到资源包会抛出异常!
PackageBundle mainBundle = manifest.GetMainPackageBundle(assetInfo.Asset);
if (checkSet.Contains(mainBundle.BundleGUID) == false)
{
checkSet.Add(mainBundle.BundleGUID);
checkList.Add(mainBundle);
}
// 注意:如果清单里未找到资源包会抛出异常!
List<PackageBundle> mainDependBundles = manifest.GetAssetAllDependencies(assetInfo.Asset);
foreach (var dependBundle in mainDependBundles)
{
if (checkSet.Contains(dependBundle.BundleGUID) == false)
{
checkSet.Add(dependBundle.BundleGUID);
checkList.Add(dependBundle);
}
}
// 下载主资源包内所有资源对象依赖的资源包
if (recursiveDownload)
{
foreach (var otherMainAsset in mainBundle.IncludeMainAssets)
{
var otherMainBundle = manifest.GetMainPackageBundle(otherMainAsset.BundleID);
if (checkSet.Contains(otherMainBundle.BundleGUID) == false)
{
checkSet.Add(otherMainBundle.BundleGUID);
checkList.Add(otherMainBundle);
}
List<PackageBundle> otherDependBundles = manifest.GetAssetAllDependencies(otherMainAsset);
foreach (var dependBundle in otherDependBundles)
{
if (checkSet.Contains(dependBundle.BundleGUID) == false)
{
checkSet.Add(dependBundle.BundleGUID);
checkList.Add(dependBundle);
}
}
}
}
}
List<BundleInfo> result = new List<BundleInfo>(1000);
foreach (var packageBundle in checkList)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedDownload(packageBundle))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
}
return result;
}
internal List<BundleInfo> GetUnpackListByAll(PackageManifest manifest)
{
if (manifest == null)
return new List<BundleInfo>();
List<BundleInfo> result = new List<BundleInfo>(1000);
foreach (var packageBundle in manifest.BundleList)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedUnpack(packageBundle))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
}
return result;
}
internal List<BundleInfo> GetUnpackListByTags(PackageManifest manifest, string[] tags)
{
if (manifest == null)
return new List<BundleInfo>();
List<BundleInfo> result = new List<BundleInfo>(1000);
foreach (var packageBundle in manifest.BundleList)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedUnpack(packageBundle))
{
if (packageBundle.HasTag(tags))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle);
result.Add(bundleInfo);
}
}
}
return result;
}
internal List<BundleInfo> GetImporterListByBundleInfos(PackageManifest manifest, ImportBundleInfo[] fileInfos)
{
if (manifest == null)
return new List<BundleInfo>();
List<BundleInfo> result = new List<BundleInfo>();
foreach (var fileInfo in fileInfos)
{
string filePath = fileInfo.FilePath;
if (string.IsNullOrEmpty(filePath))
continue;
PackageBundle packageBundle = null;
if (string.IsNullOrEmpty(fileInfo.BundleName) == false)
{
if (manifest.TryGetPackageBundleByBundleName(fileInfo.BundleName, out packageBundle) == false)
{
YooLogger.Warning($"Not found package bundle, bundle name : {fileInfo.BundleName}");
continue;
}
}
else if (string.IsNullOrEmpty(fileInfo.BundleGUID) == false)
{
if (manifest.TryGetPackageBundleByBundleGUID(fileInfo.BundleGUID, out packageBundle) == false)
{
YooLogger.Warning($"Not found package bundle, bundle guid : {fileInfo.BundleGUID}");
continue;
}
}
else
{
string fileName = System.IO.Path.GetFileName(filePath);
if (manifest.TryGetPackageBundleByFileName(fileName, out packageBundle) == false)
{
YooLogger.Warning($"Not found package bundle, file name : {fileName}");
continue;
}
}
if (packageBundle != null)
{
var fileSystem = GetBelongFileSystem(packageBundle);
if (fileSystem == null)
continue;
if (fileSystem.NeedImport(packageBundle))
{
var bundleInfo = new BundleInfo(fileSystem, packageBundle, filePath);
result.Add(bundleInfo);
}
}
}
return result;
}
#endregion
/// <summary>
/// 获取主文件系统
/// 说明:文件系统列表里,最后一个属于主文件系统
/// </summary>
public IFileSystem GetMainFileSystem()
{
int count = FileSystems.Count;
if (count == 0)
return null;
return FileSystems[count - 1];
}
/// <summary>
/// 获取资源包所属文件系统
/// </summary>
public IFileSystem GetBelongFileSystem(PackageBundle packageBundle)
{
for (int i = 0; i < FileSystems.Count; i++)
{
IFileSystem fileSystem = FileSystems[i];
if (fileSystem.Belong(packageBundle))
{
return fileSystem;
}
}
YooLogger.Error($"Can not found belong file system : {packageBundle.BundleName}");
return null;
}
}
}