mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-28 19:48:47 +00:00
refactor : 重构代码
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f2f046660639e54cb2c40610189a91c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 内置资源清单目录
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
internal class BuiltinFileCatalog
|
||||
{
|
||||
[Serializable]
|
||||
public class FileWrapper
|
||||
{
|
||||
public string BundleGUID;
|
||||
public string FileName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件版本
|
||||
/// </summary>
|
||||
public string FileVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹版本
|
||||
/// </summary>
|
||||
public string PackageVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 文件列表
|
||||
/// </summary>
|
||||
public List<FileWrapper> Wrappers = new List<FileWrapper>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b05c83971e3dca94f9fa460d396385e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,450 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 内置文件系统
|
||||
/// </summary>
|
||||
internal class BuiltinFileSystem : IFileSystem
|
||||
{
|
||||
public class FileWrapper
|
||||
{
|
||||
public string FileName { private set; get; }
|
||||
|
||||
public FileWrapper(string fileName)
|
||||
{
|
||||
FileName = fileName;
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly Dictionary<string, FileWrapper> _wrappers = new Dictionary<string, FileWrapper>(10000);
|
||||
protected readonly Dictionary<string, string> _builtinFilePathMapping = new Dictionary<string, string>(10000);
|
||||
protected IFileSystem _unpackFileSystem;
|
||||
protected string _packageRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件根目录
|
||||
/// </summary>
|
||||
public string FileRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return _packageRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _wrappers.Count;
|
||||
}
|
||||
}
|
||||
|
||||
#region 自定义参数
|
||||
/// <summary>
|
||||
/// 自定义参数:UnityWebRequest 创建委托
|
||||
/// </summary>
|
||||
public UnityWebRequestCreator WebRequestCreator { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:覆盖安装缓存清理模式
|
||||
/// </summary>
|
||||
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验级别
|
||||
/// </summary>
|
||||
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||
/// </summary>
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = 32;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:数据文件追加文件格式
|
||||
/// </summary>
|
||||
public bool AppendFileExtension { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:禁用Catalog目录查询文件
|
||||
/// </summary>
|
||||
public bool DisableCatalogFile { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:拷贝内置清单
|
||||
/// </summary>
|
||||
public bool CopyBuildinPackageManifest { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:拷贝内置清单的目标目录
|
||||
/// 注意:该参数为空的时候,会获取默认的沙盒目录!
|
||||
/// </summary>
|
||||
public string CopyBuildinPackageManifestDestRoot { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:解压文件系统的根目录
|
||||
/// </summary>
|
||||
public string UnpackFileSystemRoot { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:加载 AssetBundle 的工厂委托
|
||||
/// </summary>
|
||||
public LoadAssetBundleOperationFactory LoadAssetBundleFactory { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:加载 RawBundle 的工厂委托
|
||||
/// </summary>
|
||||
public LoadRawBundleOperationFactory LoadRawBundleFactory { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:资源清单服务类
|
||||
/// </summary>
|
||||
public IManifestRestoreServices ManifestRestoreServices { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:拷贝内置文件接口的实例类
|
||||
/// </summary>
|
||||
public ILocalFileCopyServices CopyLocalFileServices { private set; get; }
|
||||
#endregion
|
||||
|
||||
|
||||
public BuiltinFileSystem()
|
||||
{
|
||||
}
|
||||
public virtual FSInitializeOperation InitializeAsync()
|
||||
{
|
||||
var operation = new DBFSInitializeOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSRequestVersionOperation RequestVersionAsync(RequestVersionOptions options)
|
||||
{
|
||||
var operation = new BFSRequestVersionOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSLoadManifestOperation LoadManifestAsync(LoadManifestOptions options)
|
||||
{
|
||||
var operation = new BFSLoadManifestOperation(this, options.PackageVersion);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
|
||||
{
|
||||
return _unpackFileSystem.ClearCacheAsync(options);
|
||||
}
|
||||
public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options)
|
||||
{
|
||||
// 注意:业务层的解压器会依赖该方法
|
||||
options.ImportFilePath = GetBuiltinFileLoadPath(options.Bundle);
|
||||
return _unpackFileSystem.DownloadFileAsync(options);
|
||||
}
|
||||
public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
||||
{
|
||||
PackageBundle bundle = options.Bundle;
|
||||
if (IsUnpackBundleFile(bundle))
|
||||
{
|
||||
return _unpackFileSystem.LoadBundleAsync(options);
|
||||
}
|
||||
|
||||
if (bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||
{
|
||||
var operation = new BFSLoadAssetBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
else if (bundle.BundleType == (int)EBundleType.RawBundle)
|
||||
{
|
||||
var operation = new BFSLoadRawBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
#if TUANJIE_1_7_OR_NEWER
|
||||
else if (bundle.BundleType == (int)EBundleType.InstantBundle)
|
||||
{
|
||||
var operation = new BFSLoadInstantBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
string error = $"{nameof(BuiltinFileSystem)} not support load bundle type : {bundle.BundleType}";
|
||||
var operation = new FSLoadBundleCompleteOperation(error);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetParameter(string name, object value)
|
||||
{
|
||||
if (name == FileSystemParametersDefine.DOWNLOAD_BACKEND)
|
||||
{
|
||||
DownloadBackend = (IDownloadBackend)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.UNITY_WEB_REQUEST_CREATOR)
|
||||
{
|
||||
WebRequestCreator = (UnityWebRequestCreator)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
|
||||
{
|
||||
InstallClearMode = (EOverwriteInstallClearMode)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
|
||||
{
|
||||
FileVerifyLevel = (EFileVerifyLevel)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, int.MaxValue);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
|
||||
{
|
||||
AppendFileExtension = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DISABLE_CATALOG_FILE)
|
||||
{
|
||||
DisableCatalogFile = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST)
|
||||
{
|
||||
CopyBuildinPackageManifest = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST_DEST_ROOT)
|
||||
{
|
||||
CopyBuildinPackageManifestDestRoot = (string)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.UNPACK_FILE_SYSTEM_ROOT)
|
||||
{
|
||||
UnpackFileSystemRoot = (string)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.LOAD_ASSETBUNDLE_OPERATION_FACTORY)
|
||||
{
|
||||
LoadAssetBundleFactory = (LoadAssetBundleOperationFactory)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.LOAD_RAWBUNDLE_OPERATION_FACTORY)
|
||||
{
|
||||
LoadRawBundleFactory = (LoadRawBundleOperationFactory)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.MANIFEST_RESTORE_SERVICES)
|
||||
{
|
||||
ManifestRestoreServices = (IManifestRestoreServices)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES)
|
||||
{
|
||||
CopyLocalFileServices = (ILocalFileCopyServices)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning($"Invalid parameter : {name}");
|
||||
}
|
||||
}
|
||||
public virtual void OnCreate(string packageName, string packageRoot)
|
||||
{
|
||||
PackageName = packageName;
|
||||
|
||||
if (string.IsNullOrEmpty(packageRoot))
|
||||
_packageRoot = GetDefaultBuiltinPackageRoot(packageName);
|
||||
else
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(WebRequestCreator);
|
||||
|
||||
// 创建默认的 AssetBundle 加载工厂
|
||||
if (LoadAssetBundleFactory == null)
|
||||
LoadAssetBundleFactory = DefaultLoadAssetBundleOperationFactory;
|
||||
|
||||
// 创建默认的 RawBundle 加载工厂
|
||||
if (LoadRawBundleFactory == null)
|
||||
LoadRawBundleFactory = DefaultLoadRawBundleOperationFactory;
|
||||
|
||||
// 创建解压文件系统
|
||||
var remoteServices = new UnpackRemoteService(_packageRoot);
|
||||
_unpackFileSystem = new UnpackFileSystem();
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.DOWNLOAD_BACKEND, DownloadBackend);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.UNITY_WEB_REQUEST_CREATOR, WebRequestCreator);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, InstallClearMode);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_LEVEL, FileVerifyLevel);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY, FileVerifyMaxConcurrency);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, AppendFileExtension);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.LOAD_ASSETBUNDLE_OPERATION_FACTORY, LoadAssetBundleFactory);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.LOAD_RAWBUNDLE_OPERATION_FACTORY, LoadRawBundleFactory);
|
||||
_unpackFileSystem.SetParameter(FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES, CopyLocalFileServices);
|
||||
_unpackFileSystem.OnCreate(packageName, UnpackFileSystemRoot);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (_unpackFileSystem != null)
|
||||
{
|
||||
_unpackFileSystem.OnDestroy();
|
||||
_unpackFileSystem = null;
|
||||
}
|
||||
|
||||
if (DownloadBackend != null)
|
||||
{
|
||||
DownloadBackend.Dispose();
|
||||
DownloadBackend = null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Belong(PackageBundle bundle)
|
||||
{
|
||||
if (DisableCatalogFile)
|
||||
return true;
|
||||
return _wrappers.ContainsKey(bundle.BundleGUID);
|
||||
}
|
||||
public virtual bool Exists(PackageBundle bundle)
|
||||
{
|
||||
if (DisableCatalogFile)
|
||||
return true;
|
||||
return _wrappers.ContainsKey(bundle.BundleGUID);
|
||||
}
|
||||
public virtual bool NeedDownload(PackageBundle bundle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual bool NeedUnpack(PackageBundle bundle)
|
||||
{
|
||||
if (IsUnpackBundleFile(bundle))
|
||||
{
|
||||
return _unpackFileSystem.Exists(bundle) == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public virtual bool NeedImport(PackageBundle bundle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual string GetBundleFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (IsUnpackBundleFile(bundle))
|
||||
{
|
||||
return _unpackFileSystem.GetBundleFilePath(bundle);
|
||||
}
|
||||
|
||||
return GetBuiltinFileLoadPath(bundle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否属于解压资源包文件
|
||||
/// </summary>
|
||||
protected virtual bool IsUnpackBundleFile(PackageBundle bundle)
|
||||
{
|
||||
if (Belong(bundle) == false)
|
||||
return false;
|
||||
|
||||
#if UNITY_ANDROID || UNITY_OPENHARMONY
|
||||
if (bundle.Encrypted)
|
||||
return true;
|
||||
|
||||
if (bundle.BundleType == (int)EBundleType.RawBundle)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
private LoadAssetBundleOperation DefaultLoadAssetBundleOperationFactory(bool bundleEncrypted, LoadAssetBundleOptions options)
|
||||
{
|
||||
if (bundleEncrypted)
|
||||
{
|
||||
string error = $"{nameof(DefaultLoadAssetBundleOperation)} cannot load encrypted bundle. Please provide a custom {nameof(LoadAssetBundleOperationFactory)}.";
|
||||
return new LoadAssetBundleCompleteOperation(error, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DefaultLoadAssetBundleOperation(options);
|
||||
}
|
||||
}
|
||||
private LoadRawBundleOperation DefaultLoadRawBundleOperationFactory(bool bundleEncrypted, LoadRawBundleOptions options)
|
||||
{
|
||||
if (bundleEncrypted)
|
||||
{
|
||||
string error = $"{nameof(DefaultLoadRawBundleOperation)} cannot load encrypted bundle. Please provide a custom {nameof(LoadRawBundleOperationFactory)}.";
|
||||
return new LoadRawBundleCompleteOperation(error, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DefaultLoadRawBundleOperation(options);
|
||||
}
|
||||
}
|
||||
protected string GetDefaultBuiltinPackageRoot(string packageName)
|
||||
{
|
||||
string rootDirectory = YooAssetSettingsData.GetYooDefaultBuildinRoot();
|
||||
return PathUtility.Combine(rootDirectory, packageName);
|
||||
}
|
||||
public string GetBuiltinFileLoadPath(PackageBundle bundle)
|
||||
{
|
||||
if (_builtinFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
filePath = PathUtility.Combine(_packageRoot, bundle.FileName);
|
||||
_builtinFilePathMapping.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetBuiltinPackageVersionFilePath()
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public string GetBuiltinPackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public string GetBuiltinPackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public string GetCatalogBinaryFileLoadPath()
|
||||
{
|
||||
return PathUtility.Combine(_packageRoot, BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录文件信息
|
||||
/// </summary>
|
||||
public bool RecordCatalogFile(string bundleGUID, FileWrapper wrapper)
|
||||
{
|
||||
if (_wrappers.ContainsKey(bundleGUID))
|
||||
{
|
||||
YooLogger.Error($"{nameof(BuiltinFileSystem)} has element : {bundleGUID}");
|
||||
return false;
|
||||
}
|
||||
|
||||
_wrappers.Add(bundleGUID, wrapper);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化解压文件系统
|
||||
/// </summary>
|
||||
public FSInitializeOperation InitializeUnpackFileSystem()
|
||||
{
|
||||
return _unpackFileSystem.InitializeAsync();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98465b987635afc479022ec358477491
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BuiltinFileSystemConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// 内置清单JSON文件名称
|
||||
/// </summary>
|
||||
public const string BuiltinCatalogJsonFileName = "BuiltinCatalog.json";
|
||||
|
||||
/// <summary>
|
||||
/// 内置清单二进制文件名称
|
||||
/// </summary>
|
||||
public const string BuiltinCatalogBinaryFileName = "BuiltinCatalog.bytes";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4aa038f71ffd2394abc5daee917fbc66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CatalogFileConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件极限大小(100MB)
|
||||
/// </summary>
|
||||
public const int FileMaxSize = 104857600;
|
||||
|
||||
/// <summary>
|
||||
/// 文件头标记
|
||||
/// </summary>
|
||||
public const uint FileSign = 0x133C5EE;
|
||||
|
||||
/// <summary>
|
||||
/// 文件格式版本
|
||||
/// </summary>
|
||||
public const string FileVersion = "1.0.0";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6be7b8be0b51784997c959b370193e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class CatalogFileTools
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// 生成包裹的内置资源目录文件
|
||||
/// 说明:根据指定目录下的文件生成清单文件。
|
||||
/// </summary>
|
||||
public static bool CreateFile(IManifestRestoreServices services, string packageName, string packageDirectory)
|
||||
{
|
||||
// 获取资源清单版本
|
||||
string packageVersion;
|
||||
{
|
||||
string versionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||
string versionFilePath = $"{packageDirectory}/{versionFileName}";
|
||||
if (File.Exists(versionFilePath) == false)
|
||||
{
|
||||
Debug.LogError($"Can not found package version file : {versionFilePath}");
|
||||
return false;
|
||||
}
|
||||
|
||||
packageVersion = FileUtility.ReadAllText(versionFilePath);
|
||||
}
|
||||
|
||||
// 加载资源清单文件
|
||||
PackageManifest packageManifest;
|
||||
{
|
||||
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
||||
string manifestFilePath = $"{packageDirectory}/{manifestFileName}";
|
||||
if (File.Exists(manifestFilePath) == false)
|
||||
{
|
||||
Debug.LogError($"Can not found package manifest file : {manifestFilePath}");
|
||||
return false;
|
||||
}
|
||||
|
||||
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
|
||||
packageManifest = PackageManifestTools.DeserializeFromBinary(binaryData, services);
|
||||
}
|
||||
|
||||
// 获取文件名映射关系
|
||||
Dictionary<string, string> fileMapping = new Dictionary<string, string>();
|
||||
{
|
||||
foreach (var packageBundle in packageManifest.BundleList)
|
||||
{
|
||||
fileMapping.Add(packageBundle.FileName, packageBundle.BundleGUID);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建内置清单实例
|
||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
||||
buildinFileCatalog.FileVersion = CatalogFileConstants.FileVersion;
|
||||
buildinFileCatalog.PackageName = packageName;
|
||||
buildinFileCatalog.PackageVersion = packageVersion;
|
||||
|
||||
// 创建白名单查询集合
|
||||
HashSet<string> whiteFileList = new HashSet<string>
|
||||
{
|
||||
"link.xml",
|
||||
"buildlogtep.json",
|
||||
BuiltinFileSystemConstants.BuiltinCatalogJsonFileName,
|
||||
BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName
|
||||
};
|
||||
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
|
||||
string manifestBinaryFIleName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
||||
string manifestJsonFIleName = YooAssetSettingsData.GetManifestJsonFileName(packageName, packageVersion);
|
||||
string reportFileName = YooAssetSettingsData.GetBuildReportFileName(packageName, packageVersion);
|
||||
whiteFileList.Add(packageVersionFileName);
|
||||
whiteFileList.Add(packageHashFileName);
|
||||
whiteFileList.Add(manifestBinaryFIleName);
|
||||
whiteFileList.Add(manifestJsonFIleName);
|
||||
whiteFileList.Add(reportFileName);
|
||||
|
||||
// 记录所有内置资源文件
|
||||
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);
|
||||
FileInfo[] fileInfos = rootDirectory.GetFiles();
|
||||
foreach (var fileInfo in fileInfos)
|
||||
{
|
||||
if (fileInfo.Extension == ".meta")
|
||||
continue;
|
||||
|
||||
if (whiteFileList.Contains(fileInfo.Name))
|
||||
continue;
|
||||
|
||||
string fileName = fileInfo.Name;
|
||||
if (fileMapping.TryGetValue(fileName, out string bundleGUID))
|
||||
{
|
||||
var wrapper = new BuiltinFileCatalog.FileWrapper();
|
||||
wrapper.BundleGUID = bundleGUID;
|
||||
wrapper.FileName = fileName;
|
||||
buildinFileCatalog.Wrappers.Add(wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Failed mapping file : {fileName}");
|
||||
}
|
||||
}
|
||||
|
||||
// 创建输出文件
|
||||
string jsonFilePath = $"{packageDirectory}/{BuiltinFileSystemConstants.BuiltinCatalogJsonFileName}";
|
||||
if (File.Exists(jsonFilePath))
|
||||
File.Delete(jsonFilePath);
|
||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||
|
||||
// 创建输出文件
|
||||
string binaryFilePath = $"{packageDirectory}/{BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName}";
|
||||
if (File.Exists(binaryFilePath))
|
||||
File.Delete(binaryFilePath);
|
||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||
|
||||
UnityEditor.AssetDatabase.Refresh();
|
||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成空的包裹内置资源目录文件
|
||||
/// </summary>
|
||||
public static bool CreateEmptyFile(string packageName, string packageVersion, string outputPath)
|
||||
{
|
||||
// 创建内置清单实例
|
||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
||||
buildinFileCatalog.FileVersion = CatalogFileConstants.FileVersion;
|
||||
buildinFileCatalog.PackageName = packageName;
|
||||
buildinFileCatalog.PackageVersion = packageVersion;
|
||||
|
||||
// 创建输出文件
|
||||
string jsonFilePath = $"{outputPath}/{BuiltinFileSystemConstants.BuiltinCatalogJsonFileName}";
|
||||
if (File.Exists(jsonFilePath))
|
||||
File.Delete(jsonFilePath);
|
||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||
|
||||
// 创建输出文件
|
||||
string binaryFilePath = $"{outputPath}/{BuiltinFileSystemConstants.BuiltinCatalogBinaryFileName}";
|
||||
if (File.Exists(binaryFilePath))
|
||||
File.Delete(binaryFilePath);
|
||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||
|
||||
UnityEditor.AssetDatabase.Refresh();
|
||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 序列化(JSON文件)
|
||||
/// </summary>
|
||||
public static void SerializeToJson(string savePath, BuiltinFileCatalog catalog)
|
||||
{
|
||||
string json = JsonUtility.ToJson(catalog, true);
|
||||
FileUtility.WriteAllText(savePath, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化(JSON文件)
|
||||
/// </summary>
|
||||
public static BuiltinFileCatalog DeserializeFromJson(string jsonContent)
|
||||
{
|
||||
return JsonUtility.FromJson<BuiltinFileCatalog>(jsonContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化(二进制文件)
|
||||
/// </summary>
|
||||
public static void SerializeToBinary(string savePath, BuiltinFileCatalog catalog)
|
||||
{
|
||||
using (FileStream fs = new FileStream(savePath, FileMode.Create))
|
||||
{
|
||||
// 创建缓存器
|
||||
BufferWriter buffer = new BufferWriter(CatalogFileConstants.FileMaxSize);
|
||||
|
||||
// 写入文件标记
|
||||
buffer.WriteUInt32(CatalogFileConstants.FileSign);
|
||||
|
||||
// 写入文件版本
|
||||
buffer.WriteUTF8(CatalogFileConstants.FileVersion);
|
||||
|
||||
// 写入文件头信息
|
||||
buffer.WriteUTF8(catalog.PackageName);
|
||||
buffer.WriteUTF8(catalog.PackageVersion);
|
||||
|
||||
// 写入资源包列表
|
||||
buffer.WriteInt32(catalog.Wrappers.Count);
|
||||
for (int i = 0; i < catalog.Wrappers.Count; i++)
|
||||
{
|
||||
var fileWrapper = catalog.Wrappers[i];
|
||||
buffer.WriteUTF8(fileWrapper.BundleGUID);
|
||||
buffer.WriteUTF8(fileWrapper.FileName);
|
||||
}
|
||||
|
||||
// 写入文件流
|
||||
buffer.WriteToStream(fs);
|
||||
fs.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化(二进制文件)
|
||||
/// </summary>
|
||||
public static BuiltinFileCatalog DeserializeFromBinary(byte[] binaryData)
|
||||
{
|
||||
if (binaryData == null || binaryData.Length == 0)
|
||||
throw new Exception("Catalog file data is null or empty.");
|
||||
|
||||
// 创建缓存器
|
||||
BufferReader buffer = new BufferReader(binaryData);
|
||||
|
||||
// 读取文件标记
|
||||
uint fileSign = buffer.ReadUInt32();
|
||||
if (fileSign != CatalogFileConstants.FileSign)
|
||||
throw new Exception("Invalid catalog file.");
|
||||
|
||||
// 读取文件版本
|
||||
string fileVersion = buffer.ReadUTF8();
|
||||
if (fileVersion != CatalogFileConstants.FileVersion)
|
||||
throw new Exception($"The catalog file version are not compatible : {fileVersion} != {CatalogFileConstants.FileVersion}");
|
||||
|
||||
BuiltinFileCatalog catalog = new BuiltinFileCatalog();
|
||||
{
|
||||
// 读取文件头信息
|
||||
catalog.FileVersion = fileVersion;
|
||||
catalog.PackageName = buffer.ReadUTF8();
|
||||
catalog.PackageVersion = buffer.ReadUTF8();
|
||||
|
||||
// 读取资源包列表
|
||||
int fileCount = buffer.ReadInt32();
|
||||
catalog.Wrappers = new List<BuiltinFileCatalog.FileWrapper>(fileCount);
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
var fileWrapper = new BuiltinFileCatalog.FileWrapper();
|
||||
fileWrapper.BundleGUID = buffer.ReadUTF8();
|
||||
fileWrapper.FileName = buffer.ReadUTF8();
|
||||
catalog.Wrappers.Add(fileWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
return catalog;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf87ffe3b3de69942ac16640a330dd37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06f6a75331ed07a4a9e5e8f46dcf157e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,238 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DBFSInitializeOperation : FSInitializeOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadBuildinPackageVersion,
|
||||
CopyBuildinPackageHash,
|
||||
CopyBuildinPackageManifest,
|
||||
InitUnpackFileSystem,
|
||||
LoadCatalogFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private RequestBuiltinPackageVersionOperation _requestBuildinPackageVersionOp;
|
||||
private CopyBuiltinFileOperation _copyBuildinHashFileOp;
|
||||
private CopyBuiltinFileOperation _copyBuildinManifestFileOp;
|
||||
private FSInitializeOperation _initUnpackFIleSystemOp;
|
||||
private LoadBuiltinCatalogFileOperation _loadBuildinCatalogFileOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal DBFSInitializeOperation(BuiltinFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(DefaultBuildinFileSystem)} is not support WEBGL platform.";
|
||||
#else
|
||||
if (_fileSystem.CopyBuildinPackageManifest)
|
||||
_steps = ESteps.LoadBuildinPackageVersion;
|
||||
else
|
||||
_steps = ESteps.InitUnpackFileSystem;
|
||||
#endif
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadBuildinPackageVersion)
|
||||
{
|
||||
if (_requestBuildinPackageVersionOp == null)
|
||||
{
|
||||
_requestBuildinPackageVersionOp = new RequestBuiltinPackageVersionOperation(_fileSystem);
|
||||
_requestBuildinPackageVersionOp.StartOperation();
|
||||
AddChildOperation(_requestBuildinPackageVersionOp);
|
||||
}
|
||||
|
||||
_requestBuildinPackageVersionOp.UpdateOperation();
|
||||
if (_requestBuildinPackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.CopyBuildinPackageHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestBuildinPackageVersionOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CopyBuildinPackageHash)
|
||||
{
|
||||
if (_copyBuildinHashFileOp == null)
|
||||
{
|
||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
|
||||
string sourceFilePath = _fileSystem.GetBuiltinPackageHashFilePath(packageVersion);
|
||||
_copyBuildinHashFileOp = new CopyBuiltinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||
_copyBuildinHashFileOp.StartOperation();
|
||||
AddChildOperation(_copyBuildinHashFileOp);
|
||||
}
|
||||
|
||||
_copyBuildinHashFileOp.UpdateOperation();
|
||||
if (_copyBuildinHashFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_copyBuildinHashFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.CopyBuildinPackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _copyBuildinHashFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CopyBuildinPackageManifest)
|
||||
{
|
||||
if (_copyBuildinManifestFileOp == null)
|
||||
{
|
||||
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
|
||||
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
|
||||
string sourceFilePath = _fileSystem.GetBuiltinPackageManifestFilePath(packageVersion);
|
||||
_copyBuildinManifestFileOp = new CopyBuiltinFileOperation(_fileSystem, sourceFilePath, destFilePath);
|
||||
_copyBuildinManifestFileOp.StartOperation();
|
||||
AddChildOperation(_copyBuildinManifestFileOp);
|
||||
}
|
||||
|
||||
_copyBuildinManifestFileOp.UpdateOperation();
|
||||
if (_copyBuildinManifestFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_copyBuildinManifestFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.InitUnpackFileSystem;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _copyBuildinManifestFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitUnpackFileSystem)
|
||||
{
|
||||
if (_initUnpackFIleSystemOp == null)
|
||||
{
|
||||
_initUnpackFIleSystemOp = _fileSystem.InitializeUnpackFileSystem();
|
||||
_initUnpackFIleSystemOp.StartOperation();
|
||||
AddChildOperation(_initUnpackFIleSystemOp);
|
||||
}
|
||||
|
||||
_initUnpackFIleSystemOp.UpdateOperation();
|
||||
Progress = _initUnpackFIleSystemOp.Progress;
|
||||
if (_initUnpackFIleSystemOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_initUnpackFIleSystemOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
if (_fileSystem.DisableCatalogFile)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.LoadCatalogFile;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _initUnpackFIleSystemOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCatalogFile)
|
||||
{
|
||||
if (_loadBuildinCatalogFileOp == null)
|
||||
{
|
||||
_loadBuildinCatalogFileOp = new LoadBuiltinCatalogFileOperation(_fileSystem);
|
||||
_loadBuildinCatalogFileOp.StartOperation();
|
||||
AddChildOperation(_loadBuildinCatalogFileOp);
|
||||
}
|
||||
|
||||
_loadBuildinCatalogFileOp.UpdateOperation();
|
||||
if (_loadBuildinCatalogFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadBuildinCatalogFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
var catalog = _loadBuildinCatalogFileOp.Catalog;
|
||||
if (catalog == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Fatal error : catalog is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (catalog.PackageName != _fileSystem.PackageName)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var wrapper in catalog.Wrappers)
|
||||
{
|
||||
var fileWrapper = new BuiltinFileSystem.FileWrapper(wrapper.FileName);
|
||||
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
|
||||
}
|
||||
|
||||
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadBuildinCatalogFileOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCopyManifestFileRoot()
|
||||
{
|
||||
string destRoot = _fileSystem.CopyBuildinPackageManifestDestRoot;
|
||||
if (string.IsNullOrEmpty(destRoot))
|
||||
{
|
||||
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
|
||||
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||
}
|
||||
return destRoot;
|
||||
}
|
||||
private string GetCopyPackageHashDestPath(string packageVersion)
|
||||
{
|
||||
string fileRoot = GetCopyManifestFileRoot();
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, packageVersion);
|
||||
return PathUtility.Combine(fileRoot, fileName);
|
||||
}
|
||||
private string GetCopyPackageManifestDestPath(string packageVersion)
|
||||
{
|
||||
string fileRoot = GetCopyManifestFileRoot();
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, packageVersion);
|
||||
return PathUtility.Combine(fileRoot, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a15804d2ba6172a4b91f6c17245495a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,311 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载 AssetBundle 文件
|
||||
/// </summary>
|
||||
internal class BFSLoadAssetBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadBuiltinAssetBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private LoadAssetBundleOperation _loadAssetBundleOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal BFSLoadAssetBundleOperation(BuiltinFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadBuiltinAssetBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadBuiltinAssetBundle)
|
||||
{
|
||||
var options = new LoadAssetBundleOptions();
|
||||
options.FileLoadPath = _fileSystem.GetBuiltinFileLoadPath(_bundle);
|
||||
options.Bundle = _bundle;
|
||||
_loadAssetBundleOp = _fileSystem.LoadAssetBundleFactory.Invoke(_bundle.Encrypted, options);
|
||||
_loadAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadAssetBundleOp);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_loadAssetBundleOp.WaitForCompletion();
|
||||
|
||||
_loadAssetBundleOp.UpdateOperation();
|
||||
if (_loadAssetBundleOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadAssetBundleOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
if (_loadAssetBundleOp.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Loaded builtin asset bundle is null.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new AssetBundleResult(_fileSystem, _bundle, _loadAssetBundleOp.Result, _loadAssetBundleOp.ManagedStream);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadAssetBundleOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载 RawBundle 文件
|
||||
/// </summary>
|
||||
internal class BFSLoadRawBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadBuiltinRawBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private LoadRawBundleOperation _loadRawBundleOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal BFSLoadRawBundleOperation(BuiltinFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadBuiltinRawBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadBuiltinRawBundle)
|
||||
{
|
||||
var options = new LoadRawBundleOptions();
|
||||
options.FileLoadPath = _fileSystem.GetBuiltinFileLoadPath(_bundle);
|
||||
options.Bundle = _bundle;
|
||||
_loadRawBundleOp = _fileSystem.LoadRawBundleFactory.Invoke(_bundle.Encrypted, options);
|
||||
_loadRawBundleOp.StartOperation();
|
||||
AddChildOperation(_loadRawBundleOp);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_loadRawBundleOp.WaitForCompletion();
|
||||
|
||||
_loadRawBundleOp.UpdateOperation();
|
||||
if (_loadRawBundleOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadRawBundleOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
if (_loadRawBundleOp.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Loaded builtin raw bundle is null.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new RawBundleResult(_fileSystem, _bundle, _loadRawBundleOp.Result);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadRawBundleOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
||||
#if TUANJIE_1_7_OR_NEWER
|
||||
/// <summary>
|
||||
/// 加载团结文件
|
||||
/// </summary>
|
||||
internal class BFSLoadInstantBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadInstantBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultBuildinFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private AssetBundleCreateRequest _createRequest;
|
||||
private AssetBundle _assetBundle;
|
||||
private Stream _managedStream;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal BFSLoadInstantBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadInstantBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadInstantBundle)
|
||||
{
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
if (_fileSystem.DecryptionServices == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"The {nameof(IDecryptionServices)} is null.";
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWaitingForAsyncComplete)
|
||||
{
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
var decryptResult = _fileSystem.LoadEncryptedAssetBundle(_bundle);
|
||||
_assetBundle = decryptResult.Result;
|
||||
_managedStream = decryptResult.ManagedStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
|
||||
_assetBundle = AssetBundle.LoadFromFile(filePath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
var decryptResult = _fileSystem.LoadEncryptedAssetBundleAsync(_bundle);
|
||||
_createRequest = decryptResult.CreateRequest;
|
||||
_managedStream = decryptResult.ManagedStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (_createRequest != null)
|
||||
{
|
||||
if (IsWaitingForAsyncComplete)
|
||||
{
|
||||
// 强制挂起主线程(注意:该操作会很耗时)
|
||||
YooLogger.Warning("Suspend the main thread to load unity bundle.");
|
||||
_assetBundle = _createRequest.assetBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_createRequest.isDone == false)
|
||||
return;
|
||||
_assetBundle = _createRequest.assetBundle;
|
||||
}
|
||||
}
|
||||
|
||||
if (_assetBundle == null)
|
||||
{
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load encrypted buildin asset bundle file : {_bundle.BundleName}";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load buildin asset bundle file : {_bundle.BundleName}";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream);
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
RunBatchExecution();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99fc95c784d960c45ba9373f31fbc7fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BFSLoadManifestOperation : FSLoadManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
RequestBuiltinPackageHash,
|
||||
LoadBuiltinPackageManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private RequestBuiltinPackageHashOperation _requestBuiltinPackageHashOp;
|
||||
private LoadBuiltinPackageManifestOperation _loadBuiltinPackageManifestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
public BFSLoadManifestOperation(BuiltinFileSystem fileSystem, string packageVersion)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.RequestBuiltinPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.RequestBuiltinPackageHash)
|
||||
{
|
||||
if (_requestBuiltinPackageHashOp == null)
|
||||
{
|
||||
_requestBuiltinPackageHashOp = new RequestBuiltinPackageHashOperation(_fileSystem, _packageVersion);
|
||||
_requestBuiltinPackageHashOp.StartOperation();
|
||||
AddChildOperation(_requestBuiltinPackageHashOp);
|
||||
}
|
||||
|
||||
_requestBuiltinPackageHashOp.UpdateOperation();
|
||||
if (_requestBuiltinPackageHashOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestBuiltinPackageHashOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadBuiltinPackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestBuiltinPackageHashOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadBuiltinPackageManifest)
|
||||
{
|
||||
if (_loadBuiltinPackageManifestOp == null)
|
||||
{
|
||||
string packageHash = _requestBuiltinPackageHashOp.PackageHash;
|
||||
_loadBuiltinPackageManifestOp = new LoadBuiltinPackageManifestOperation(_fileSystem, _packageVersion, packageHash);
|
||||
_loadBuiltinPackageManifestOp.StartOperation();
|
||||
AddChildOperation(_loadBuiltinPackageManifestOp);
|
||||
}
|
||||
|
||||
_loadBuiltinPackageManifestOp.UpdateOperation();
|
||||
if (_loadBuiltinPackageManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadBuiltinPackageManifestOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _loadBuiltinPackageManifestOp.Manifest;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadBuiltinPackageManifestOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b55b3624add2db6489954d999b13a9ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BFSRequestVersionOperation : FSRequestVersionOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
RequestPackageVersion,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private RequestBuiltinPackageVersionOperation _requestBuiltinPackageVersionOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal BFSRequestVersionOperation(BuiltinFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.RequestPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.RequestPackageVersion)
|
||||
{
|
||||
if (_requestBuiltinPackageVersionOp == null)
|
||||
{
|
||||
_requestBuiltinPackageVersionOp = new RequestBuiltinPackageVersionOperation(_fileSystem);
|
||||
_requestBuiltinPackageVersionOp.StartOperation();
|
||||
AddChildOperation(_requestBuiltinPackageVersionOp);
|
||||
}
|
||||
|
||||
_requestBuiltinPackageVersionOp.UpdateOperation();
|
||||
if (_requestBuiltinPackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestBuiltinPackageVersionOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
PackageVersion = _requestBuiltinPackageVersionOp.PackageVersion;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestBuiltinPackageVersionOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0b6ec24639af3741847a6a7ef09986a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be1c19353672bb34ca3e4ddcb462402f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CopyBuiltinFileOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckFileExist,
|
||||
TryCopyFile,
|
||||
UnpackFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly string _sourceFilePath;
|
||||
private readonly string _destFilePath;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public CopyBuiltinFileOperation(BuiltinFileSystem fileSystem, string sourceFilePath, string destFilePath)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_sourceFilePath = sourceFilePath;
|
||||
_destFilePath = destFilePath;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckFileExist;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckFileExist)
|
||||
{
|
||||
if (File.Exists(_destFilePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.TryCopyFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.TryCopyFile)
|
||||
{
|
||||
if (File.Exists(_sourceFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var directory = Path.GetDirectoryName(_destFilePath);
|
||||
if (Directory.Exists(directory) == false)
|
||||
Directory.CreateDirectory(directory);
|
||||
File.Copy(_sourceFilePath, _destFilePath, true);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
YooLogger.Warning($"Failed copy buildin file : {ex.Message}");
|
||||
_steps = ESteps.UnpackFile;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.UnpackFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UnpackFile)
|
||||
{
|
||||
if (_webFileRequestOp == null)
|
||||
{
|
||||
string url = DownloadSystemTools.ToLocalURL(_sourceFilePath);
|
||||
var args = new DownloadFileRequestArgs(url, _destFilePath, 60, 0);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webFileRequestOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf44368bc5c2bf1479c36d82e931c295
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class LoadBuiltinCatalogFileOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadFileData,
|
||||
RequestFileData,
|
||||
LoadCatalog,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 内置资源目录
|
||||
/// </summary>
|
||||
public BuiltinFileCatalog Catalog;
|
||||
|
||||
internal LoadBuiltinCatalogFileOperation(BuiltinFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.TryLoadFileData;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadFileData)
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_fileData = File.ReadAllBytes(filePath);
|
||||
_steps = ESteps.LoadCatalog;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.RequestFileData;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.RequestFileData)
|
||||
{
|
||||
if (_webDataRequestOp == null)
|
||||
{
|
||||
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
|
||||
string url = DownloadSystemTools.ToLocalURL(filePath);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileData = _webDataRequestOp.Result;
|
||||
_steps = ESteps.LoadCatalog;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webDataRequestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCatalog)
|
||||
{
|
||||
try
|
||||
{
|
||||
Catalog = CatalogFileTools.DeserializeFromBinary(_fileData);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load catalog file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4113df346bbd1b4ead918b52ac46f55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,134 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class LoadBuiltinPackageManifestOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadFileData,
|
||||
RequestFileData,
|
||||
VerifyFileData,
|
||||
LoadManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly string _packageHash;
|
||||
private IDownloadBytesRequest _webDataRequestOp;
|
||||
private DeserializeManifestOperation _deserializer;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹清单
|
||||
/// </summary>
|
||||
public PackageManifest Manifest { private set; get; }
|
||||
|
||||
|
||||
internal LoadBuiltinPackageManifestOperation(BuiltinFileSystem fileSystem, string packageVersion, string packageHash)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_packageHash = packageHash;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.TryLoadFileData;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadFileData)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageManifestFilePath(_packageVersion);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_fileData = File.ReadAllBytes(filePath);
|
||||
_steps = ESteps.VerifyFileData;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.RequestFileData;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.RequestFileData)
|
||||
{
|
||||
if (_webDataRequestOp == null)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageManifestFilePath(_packageVersion);
|
||||
string url = DownloadSystemTools.ToLocalURL(filePath);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webDataRequestOp = _fileSystem.DownloadBackend.CreateBytesRequest(args);
|
||||
_webDataRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webDataRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileData = _webDataRequestOp.Result;
|
||||
_steps = ESteps.VerifyFileData;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webDataRequestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyFileData)
|
||||
{
|
||||
if (PackageManifestTools.VerifyManifestData(_fileData, _packageHash))
|
||||
{
|
||||
_steps = ESteps.LoadManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Failed to verify buildin package manifest file.";
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadManifest)
|
||||
{
|
||||
if (_deserializer == null)
|
||||
{
|
||||
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestRestoreServices, _fileData);
|
||||
_deserializer.StartOperation();
|
||||
AddChildOperation(_deserializer);
|
||||
}
|
||||
|
||||
_deserializer.UpdateOperation();
|
||||
Progress = _deserializer.Progress;
|
||||
if (_deserializer.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_deserializer.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _deserializer.Manifest;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _deserializer.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
return $"PackageVersion : {_packageVersion} PackageHash : {_packageHash}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8af9b72837c6a01428ee627011f4341b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RequestBuiltinPackageHashOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadPackageHash,
|
||||
RequestPackageHash,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹哈希值
|
||||
/// </summary>
|
||||
public string PackageHash { private set; get; }
|
||||
|
||||
|
||||
internal RequestBuiltinPackageHashOperation(BuiltinFileSystem fileSystem, string packageVersion)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.TryLoadPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadPackageHash)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageHashFilePath(_packageVersion);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
PackageHash = File.ReadAllText(filePath);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.RequestPackageHash;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.RequestPackageHash)
|
||||
{
|
||||
if (_webTextRequestOp == null)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageHashFilePath(_packageVersion);
|
||||
string url = DownloadSystemTools.ToLocalURL(filePath);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageHash = _webTextRequestOp.Result;
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webTextRequestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PackageHash))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Builtin package hash file content is empty.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2084625d8253164aa71ef934e0690fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RequestBuiltinPackageVersionOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadPackageVersion,
|
||||
RequestPackageVersion,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly BuiltinFileSystem _fileSystem;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹版本
|
||||
/// </summary>
|
||||
public string PackageVersion { private set; get; }
|
||||
|
||||
|
||||
internal RequestBuiltinPackageVersionOperation(BuiltinFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.TryLoadPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadPackageVersion)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageVersionFilePath();
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
PackageVersion = File.ReadAllText(filePath);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.RequestPackageVersion;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.RequestPackageVersion)
|
||||
{
|
||||
if (_webTextRequestOp == null)
|
||||
{
|
||||
string filePath = _fileSystem.GetBuiltinPackageVersionFilePath();
|
||||
string url = DownloadSystemTools.ToLocalURL(filePath);
|
||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webTextRequestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Builtin package version file content is empty.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bddb076e377b66488ec28c9dbdd18cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b03f54c14ce3f6041870eaa9317d2e64
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序水印
|
||||
/// </summary>
|
||||
internal class ApplicationFootprint
|
||||
{
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private string _footPrint;
|
||||
|
||||
|
||||
public ApplicationFootprint(CacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取应用程序水印
|
||||
/// </summary>
|
||||
public void Load(string packageName)
|
||||
{
|
||||
string footPrintFilePath = _fileSystem.GetSandboxAppFootPrintFilePath();
|
||||
if (File.Exists(footPrintFilePath))
|
||||
{
|
||||
_footPrint = FileUtility.ReadAllText(footPrintFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Coverage(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测水印是否发生变化
|
||||
/// </summary>
|
||||
public bool IsDirty()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return _footPrint != Application.version;
|
||||
#else
|
||||
return _footPrint != Application.buildGUID;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 覆盖掉水印
|
||||
/// </summary>
|
||||
public void Coverage(string packageName)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
_footPrint = Application.version;
|
||||
#else
|
||||
_footPrint = Application.buildGUID;
|
||||
#endif
|
||||
string footPrintFilePath = _fileSystem.GetSandboxAppFootPrintFilePath();
|
||||
FileUtility.WriteAllText(footPrintFilePath, _footPrint);
|
||||
YooLogger.Log($"Save application foot print : {_footPrint}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9d96ea955bc07149a08471e33915556
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,518 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存文件系统
|
||||
/// 说明:正在进行的下载器会在ResourcePackage销毁的时候执行Abort操作!
|
||||
/// </summary>
|
||||
internal class CacheFileSystem : IFileSystem
|
||||
{
|
||||
protected readonly Dictionary<string, string> _tempFilePathMapping = new Dictionary<string, string>(10000);
|
||||
|
||||
protected string _packageRoot;
|
||||
protected string _tempFilesRoot;
|
||||
protected string _cacheBundleFilesRoot;
|
||||
protected string _cacheManifestFilesRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 文件缓存系统
|
||||
/// </summary>
|
||||
public BundleCache Cache { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载调度器
|
||||
/// </summary>
|
||||
public DownloadSchedulerOperation DownloadScheduler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件根目录
|
||||
/// </summary>
|
||||
public string FileRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return _packageRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return Cache.FileCount;
|
||||
}
|
||||
}
|
||||
|
||||
#region 自定义参数
|
||||
/// <summary>
|
||||
/// 自定义参数:UnityWebRequest 创建委托
|
||||
/// </summary>
|
||||
public UnityWebRequestCreator WebRequestCreator { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:远程服务接口的实例类
|
||||
/// </summary>
|
||||
public IRemoteServices RemoteServices { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:覆盖安装缓存清理模式
|
||||
/// </summary>
|
||||
public EOverwriteInstallClearMode InstallClearMode { private set; get; } = EOverwriteInstallClearMode.ClearAllManifestFiles;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验级别
|
||||
/// </summary>
|
||||
public EFileVerifyLevel FileVerifyLevel { private set; get; } = EFileVerifyLevel.Middle;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:初始化的时候缓存文件校验最大并发数
|
||||
/// 默认值:8(推荐范围 1-32)
|
||||
/// 说明:过大的值可能导致线程池任务过多,影响系统稳定性
|
||||
/// </summary>
|
||||
public int FileVerifyMaxConcurrency { private set; get; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:数据文件追加文件格式
|
||||
/// </summary>
|
||||
public bool AppendFileExtension { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:禁用边玩边下机制
|
||||
/// </summary>
|
||||
public bool DisableOnDemandDownload { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:最大并发连接数
|
||||
/// 默认值:8(推荐范围 1-32)
|
||||
/// 说明:过大的并发数可能被服务器限流,也会增加本地资源消耗
|
||||
/// </summary>
|
||||
public int DownloadMaxConcurrency { private set; get; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:每帧发起的最大请求数
|
||||
/// 默认值:8(推荐范围 1-32)
|
||||
/// 说明:避免单帧发起过多请求导致卡顿
|
||||
/// </summary>
|
||||
public int DownloadMaxRequestPerFrame { private set; get; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:下载任务的看门狗机制超时时间
|
||||
/// </summary>
|
||||
public int DownloadWatchDogTimeout { private set; get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:启用断点续传的最小尺寸
|
||||
/// </summary>
|
||||
public long ResumeDownloadMinimumSize { private set; get; } = long.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:断点续传下载器关注的错误码
|
||||
/// </summary>
|
||||
public List<long> ResumeDownloadResponseCodes { private set; get; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:加载 AssetBundle 的工厂委托
|
||||
/// </summary>
|
||||
public LoadAssetBundleOperationFactory LoadAssetBundleFactory { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:加载 RawBundle 的工厂委托
|
||||
/// </summary>
|
||||
public LoadRawBundleOperationFactory LoadRawBundleFactory { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:资源清单服务类
|
||||
/// </summary>
|
||||
public IManifestRestoreServices ManifestRestoreServices { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数:拷贝内置文件接口的实例类
|
||||
/// </summary>
|
||||
public ILocalFileCopyServices CopyLocalFileServices { private set; get; }
|
||||
#endregion
|
||||
|
||||
|
||||
public CacheFileSystem()
|
||||
{
|
||||
}
|
||||
public virtual FSInitializeOperation InitializeAsync()
|
||||
{
|
||||
var operation = new CFSInitializeOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSRequestVersionOperation RequestVersionAsync(RequestVersionOptions options)
|
||||
{
|
||||
var operation = new CFSRequestPackageVersionOperation(this, options.AppendTimeTicks, options.Timeout);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSLoadManifestOperation LoadManifestAsync(LoadManifestOptions options)
|
||||
{
|
||||
var operation = new CFSLoadPackageManifestOperation(this, options.PackageVersion, options.Timeout);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
|
||||
{
|
||||
if (options.ClearMode == EFileClearMode.ClearAllBundleFiles.ToString())
|
||||
{
|
||||
var operation = new ClearAllCacheBundleFilesOperation(this);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearUnusedBundleFiles.ToString())
|
||||
{
|
||||
var operation = new ClearUnusedCacheBundleFilesOperation(this, options.Manifest);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearBundleFilesByLocations.ToString())
|
||||
{
|
||||
var operation = new ClearCacheBundleFilesByLocationsOperation(this, options.Manifest, options.ClearParam);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearBundleFilesByTags.ToString())
|
||||
{
|
||||
var operation = new ClearCacheBundleFilesByTagsOperation(this, options.Manifest, options.ClearParam);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearAllManifestFiles.ToString())
|
||||
{
|
||||
var operation = new ClearAllCacheManifestFilesOperation(this);
|
||||
return operation;
|
||||
}
|
||||
else if (options.ClearMode == EFileClearMode.ClearUnusedManifestFiles.ToString())
|
||||
{
|
||||
var operation = new ClearUnusedCacheManifestFilesOperation(this, options.Manifest);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = $"Invalid clear mode : {options.ClearMode}";
|
||||
var operation = new FSClearCacheCompleteOperation(error);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options)
|
||||
{
|
||||
// 获取下载地址
|
||||
PackageBundle bundle = options.Bundle;
|
||||
if (string.IsNullOrEmpty(options.ImportFilePath))
|
||||
{
|
||||
// 注意:如果是解压文件系统类,这里会返回本地内置文件的下载路径
|
||||
string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName);
|
||||
string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName);
|
||||
options.SetURL(mainURL, fallbackURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 注意:把本地导入文件路径转换为下载器请求地址
|
||||
string mainURL = DownloadSystemTools.ToLocalURL(options.ImportFilePath);
|
||||
options.SetURL(mainURL, mainURL);
|
||||
}
|
||||
|
||||
var downloader = new DownloadPackageBundleOperation(this, options);
|
||||
return downloader;
|
||||
}
|
||||
public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
||||
{
|
||||
PackageBundle bundle = options.Bundle;
|
||||
if (bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||
{
|
||||
var operation = new CFSLoadAssetBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
else if (bundle.BundleType == (int)EBundleType.RawBundle)
|
||||
{
|
||||
var operation = new CFSLoadRawBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = $"{nameof(CacheFileSystem)} not support load bundle type : {bundle.BundleType}";
|
||||
var operation = new FSLoadBundleCompleteOperation(error);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetParameter(string name, object value)
|
||||
{
|
||||
if (name == FileSystemParametersDefine.DOWNLOAD_BACKEND)
|
||||
{
|
||||
DownloadBackend = (IDownloadBackend)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.UNITY_WEB_REQUEST_CREATOR)
|
||||
{
|
||||
WebRequestCreator = (UnityWebRequestCreator)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.REMOTE_SERVICES)
|
||||
{
|
||||
RemoteServices = (IRemoteServices)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.INSTALL_CLEAR_MODE)
|
||||
{
|
||||
InstallClearMode = (EOverwriteInstallClearMode)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_LEVEL)
|
||||
{
|
||||
FileVerifyLevel = (EFileVerifyLevel)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.FILE_VERIFY_MAX_CONCURRENCY)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
if (convertValue > 32)
|
||||
{
|
||||
YooLogger.Warning($"FILE_VERIFY_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32.");
|
||||
}
|
||||
|
||||
// 限制在合理范围内:1-32
|
||||
FileVerifyMaxConcurrency = Mathf.Clamp(convertValue, 1, 32);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.APPEND_FILE_EXTENSION)
|
||||
{
|
||||
AppendFileExtension = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DISABLE_ONDEMAND_DOWNLOAD)
|
||||
{
|
||||
DisableOnDemandDownload = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_CONCURRENCY)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
if (convertValue > 32)
|
||||
{
|
||||
YooLogger.Warning($"DOWNLOAD_MAX_CONCURRENCY value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32.");
|
||||
}
|
||||
|
||||
// 限制在合理范围内:1-32
|
||||
DownloadMaxConcurrency = Mathf.Clamp(convertValue, 1, 32);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_MAX_REQUEST_PER_FRAME)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
if (convertValue > 32)
|
||||
{
|
||||
YooLogger.Warning($"DOWNLOAD_MAX_REQUEST_PER_FRAME value {convertValue} is too large, clamped to 32. Recommended range: 1 - 32.");
|
||||
}
|
||||
|
||||
// 限制在合理范围内:1-32
|
||||
DownloadMaxRequestPerFrame = Mathf.Clamp(convertValue, 1, 32);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.DOWNLOAD_WATCH_DOG_TIME)
|
||||
{
|
||||
int convertValue = Convert.ToInt32(value);
|
||||
DownloadWatchDogTimeout = Mathf.Clamp(convertValue, 0, int.MaxValue);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_MINMUM_SIZE)
|
||||
{
|
||||
ResumeDownloadMinimumSize = Convert.ToInt64(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.RESUME_DOWNLOAD_RESPONSE_CODES)
|
||||
{
|
||||
ResumeDownloadResponseCodes = (List<long>)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.LOAD_ASSETBUNDLE_OPERATION_FACTORY)
|
||||
{
|
||||
LoadAssetBundleFactory = (LoadAssetBundleOperationFactory)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.LOAD_RAWBUNDLE_OPERATION_FACTORY)
|
||||
{
|
||||
LoadRawBundleFactory = (LoadRawBundleOperationFactory)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.MANIFEST_RESTORE_SERVICES)
|
||||
{
|
||||
ManifestRestoreServices = (IManifestRestoreServices)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.COPY_LOCAL_FILE_SERVICES)
|
||||
{
|
||||
CopyLocalFileServices = (ILocalFileCopyServices)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning($"Invalid parameter : {name}");
|
||||
}
|
||||
}
|
||||
public virtual void OnCreate(string packageName, string packageRoot)
|
||||
{
|
||||
PackageName = packageName;
|
||||
|
||||
if (string.IsNullOrEmpty(packageRoot))
|
||||
_packageRoot = GetDefaultCachePackageRoot(packageName);
|
||||
else
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
|
||||
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
||||
|
||||
// 创建文件缓存系统
|
||||
Cache = new BundleCache(PackageName, _cacheBundleFilesRoot, AppendFileExtension);
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(WebRequestCreator);
|
||||
|
||||
// 创建默认的 AssetBundle 加载工厂
|
||||
if (LoadAssetBundleFactory == null)
|
||||
LoadAssetBundleFactory = DefaultLoadAssetBundleOperationFactory;
|
||||
|
||||
// 创建默认的 RawBundle 加载工厂
|
||||
if (LoadRawBundleFactory == null)
|
||||
LoadRawBundleFactory = DefaultLoadRawBundleOperationFactory;
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (DownloadScheduler != null)
|
||||
{
|
||||
DownloadScheduler.Dispose();
|
||||
DownloadScheduler = null;
|
||||
}
|
||||
|
||||
if (DownloadBackend != null)
|
||||
{
|
||||
DownloadBackend.Dispose();
|
||||
DownloadBackend = null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Belong(PackageBundle bundle)
|
||||
{
|
||||
// 注意:缓存文件系统保底加载!
|
||||
return true;
|
||||
}
|
||||
public virtual bool Exists(PackageBundle bundle)
|
||||
{
|
||||
return Cache.IsCached(bundle.BundleGUID);
|
||||
}
|
||||
public virtual bool NeedDownload(PackageBundle bundle)
|
||||
{
|
||||
if (Belong(bundle) == false)
|
||||
return false;
|
||||
|
||||
return Exists(bundle) == false;
|
||||
}
|
||||
public virtual bool NeedUnpack(PackageBundle bundle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual bool NeedImport(PackageBundle bundle)
|
||||
{
|
||||
if (Belong(bundle) == false)
|
||||
return false;
|
||||
|
||||
return Exists(bundle) == false;
|
||||
}
|
||||
public virtual string GetBundleFilePath(PackageBundle bundle)
|
||||
{
|
||||
return GetCacheBundleFileLoadPath(bundle);
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
private LoadAssetBundleOperation DefaultLoadAssetBundleOperationFactory(bool bundleEncrypted, LoadAssetBundleOptions options)
|
||||
{
|
||||
if (bundleEncrypted)
|
||||
{
|
||||
string error = $"{nameof(DefaultLoadAssetBundleOperation)} cannot load encrypted bundle. Please provide a custom {nameof(LoadAssetBundleOperationFactory)}.";
|
||||
return new LoadAssetBundleCompleteOperation(error, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DefaultLoadAssetBundleOperation(options);
|
||||
}
|
||||
}
|
||||
private LoadRawBundleOperation DefaultLoadRawBundleOperationFactory(bool bundleEncrypted, LoadRawBundleOptions options)
|
||||
{
|
||||
if (bundleEncrypted)
|
||||
{
|
||||
string error = $"{nameof(DefaultLoadRawBundleOperation)} cannot load encrypted bundle. Please provide a custom {nameof(LoadRawBundleOperationFactory)}.";
|
||||
return new LoadRawBundleCompleteOperation(error, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DefaultLoadRawBundleOperation(options);
|
||||
}
|
||||
}
|
||||
public string GetDefaultCachePackageRoot(string packageName)
|
||||
{
|
||||
string rootDirectory = YooAssetSettingsData.GetYooDefaultCacheRoot();
|
||||
return PathUtility.Combine(rootDirectory, packageName);
|
||||
}
|
||||
public string GetCacheBundleFileLoadPath(PackageBundle bundle)
|
||||
{
|
||||
var entry = Cache.GetEntry(bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
throw new YooInternalException();
|
||||
|
||||
return entry.DataFilePath;
|
||||
}
|
||||
public string GetCachePackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
|
||||
}
|
||||
public string GetCachePackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
|
||||
}
|
||||
public string GetSandboxAppFootPrintFilePath()
|
||||
{
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName);
|
||||
}
|
||||
public string GetCacheBundleFilesRoot()
|
||||
{
|
||||
return _cacheBundleFilesRoot;
|
||||
}
|
||||
public string GetCacheManifestFilesRoot()
|
||||
{
|
||||
return _cacheManifestFilesRoot;
|
||||
}
|
||||
public string GetTempFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_tempFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
filePath = PathUtility.Combine(_tempFilesRoot, bundle.BundleGUID);
|
||||
_tempFilePathMapping.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有缓存的资源文件
|
||||
/// </summary>
|
||||
public void DeleteAllBundleFiles()
|
||||
{
|
||||
if (Directory.Exists(_cacheBundleFilesRoot))
|
||||
{
|
||||
Directory.Delete(_cacheBundleFilesRoot, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有缓存的清单文件
|
||||
/// </summary>
|
||||
public void DeleteAllManifestFiles()
|
||||
{
|
||||
if (Directory.Exists(_cacheManifestFilesRoot))
|
||||
{
|
||||
Directory.Delete(_cacheManifestFilesRoot, true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4989ddcb6c99102429eeefffc3675ae5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DefaultCacheFileSystemDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string BundleFilesFolderName = "BundleFiles";
|
||||
|
||||
/// <summary>
|
||||
/// 临时文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string TempFilesFolderName = "TempFiles";
|
||||
|
||||
/// <summary>
|
||||
/// 清单文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string ManifestFilesFolderName = "ManifestFiles";
|
||||
|
||||
/// <summary>
|
||||
/// 记录应用程序版本的文件名称
|
||||
/// </summary>
|
||||
public const string AppFootPrintFileName = "ApplicationFootPrint.bytes";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 610912866fe58794a904b43c2e24d84d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件清理方式
|
||||
/// </summary>
|
||||
public enum EFileClearMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理所有文件
|
||||
/// </summary>
|
||||
ClearAllBundleFiles,
|
||||
|
||||
/// <summary>
|
||||
/// 清理未在使用的文件
|
||||
/// </summary>
|
||||
ClearUnusedBundleFiles,
|
||||
|
||||
/// <summary>
|
||||
/// 清理指定地址的文件
|
||||
/// 说明:需要指定参数,可选:string, string[], List<string>
|
||||
/// </summary>
|
||||
ClearBundleFilesByLocations,
|
||||
|
||||
/// <summary>
|
||||
/// 清理指定标签的文件
|
||||
/// 说明:需要指定参数,可选:string, string[], List<string>
|
||||
/// </summary>
|
||||
ClearBundleFilesByTags,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有清单
|
||||
/// </summary>
|
||||
ClearAllManifestFiles,
|
||||
|
||||
/// <summary>
|
||||
/// 清理未在使用的清单
|
||||
/// </summary>
|
||||
ClearUnusedManifestFiles,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2930435fc2ba91c4ba511260b9d119d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 覆盖安装清理模式
|
||||
/// </summary>
|
||||
public enum EOverwriteInstallClearMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 不做任何处理
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存文件(包含资源文件和清单文件)
|
||||
/// </summary>
|
||||
ClearAllCacheFiles = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存的资源文件
|
||||
/// </summary>
|
||||
ClearAllBundleFiles = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存的清单文件
|
||||
/// </summary>
|
||||
ClearAllManifestFiles = 3,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c61fdc079dca97548a0158b8100ec258
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09e4cebb2073ab945ac09e9099b327ad
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CFSInitializeOperation : FSInitializeOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckAppFootPrint,
|
||||
CacheInitialize,
|
||||
CreateDownloadScheduler,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private FCInitializeOperation _initializeCacheOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal CFSInitializeOperation(CacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(DefaultCacheFileSystem)} is not support WEBGL platform.";
|
||||
#else
|
||||
_steps = ESteps.CheckAppFootPrint;
|
||||
#endif
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckAppFootPrint)
|
||||
{
|
||||
var appFootPrint = new ApplicationFootprint(_fileSystem);
|
||||
appFootPrint.Load(_fileSystem.PackageName);
|
||||
|
||||
// 如果水印发生变化,则说明覆盖安装后首次打开游戏
|
||||
if (appFootPrint.IsDirty())
|
||||
{
|
||||
if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.None)
|
||||
{
|
||||
YooLogger.Warning("Do nothing when overwrite install application.");
|
||||
}
|
||||
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllCacheFiles)
|
||||
{
|
||||
_fileSystem.DeleteAllBundleFiles();
|
||||
_fileSystem.DeleteAllManifestFiles();
|
||||
YooLogger.Warning("Delete all cache files when overwrite install application.");
|
||||
}
|
||||
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllBundleFiles)
|
||||
{
|
||||
_fileSystem.DeleteAllBundleFiles();
|
||||
YooLogger.Warning("Delete all bundle files when overwrite install application.");
|
||||
}
|
||||
else if (_fileSystem.InstallClearMode == EOverwriteInstallClearMode.ClearAllManifestFiles)
|
||||
{
|
||||
_fileSystem.DeleteAllManifestFiles();
|
||||
YooLogger.Warning("Delete all manifest files when overwrite install application.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException(_fileSystem.InstallClearMode.ToString());
|
||||
}
|
||||
|
||||
appFootPrint.Coverage(_fileSystem.PackageName);
|
||||
}
|
||||
|
||||
_steps = ESteps.CacheInitialize;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CacheInitialize)
|
||||
{
|
||||
if (_initializeCacheOp == null)
|
||||
{
|
||||
var options = new FCInitializeOptions();
|
||||
options.FileVerifyLevel = _fileSystem.FileVerifyLevel;
|
||||
options.FileVerifyMaxConcurrency = _fileSystem.FileVerifyMaxConcurrency;
|
||||
_initializeCacheOp = _fileSystem.Cache.InitializeAsync(options);
|
||||
_initializeCacheOp.StartOperation();
|
||||
AddChildOperation(_initializeCacheOp);
|
||||
}
|
||||
|
||||
_initializeCacheOp.UpdateOperation();
|
||||
Progress = _initializeCacheOp.Progress;
|
||||
if (_initializeCacheOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_initializeCacheOp.Status != EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _initializeCacheOp.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CreateDownloadScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CreateDownloadScheduler)
|
||||
{
|
||||
// 注意:下载中心作为独立任务运行!
|
||||
if (_fileSystem.DownloadScheduler == null)
|
||||
{
|
||||
_fileSystem.DownloadScheduler = new DownloadSchedulerOperation(_fileSystem);
|
||||
AsyncOperationSystem.StartOperation(_fileSystem.PackageName, _fileSystem.DownloadScheduler);
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 443aa31f081edfd458a90e3385a75203
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CFSLoadAssetBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExist,
|
||||
DownloadFile,
|
||||
AbortDownload,
|
||||
LoadCacheAssetBundle,
|
||||
CheckResult,
|
||||
TryFallback,
|
||||
Done,
|
||||
}
|
||||
|
||||
protected readonly CacheFileSystem _fileSystem;
|
||||
protected readonly PackageBundle _bundle;
|
||||
protected FSDownloadFileOperation _downloadFileOp;
|
||||
protected LoadAssetBundleOperation _loadAssetBundleOp;
|
||||
protected ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal CFSLoadAssetBundleOperation(CacheFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckExist;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckExist)
|
||||
{
|
||||
if (_fileSystem.Exists(_bundle))
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadCacheAssetBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fileSystem.DisableOnDemandDownload)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"The bundle not cached : {_bundle.BundleName}";
|
||||
YooLogger.Warning(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.DownloadFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
// 中断下载
|
||||
if (AbortDownloadFile)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
_downloadFileOp.AbortOperation();
|
||||
_steps = ESteps.AbortDownload;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
if (_downloadFileOp == null)
|
||||
{
|
||||
DownloadFileOptions options = new DownloadFileOptions(_bundle, int.MaxValue);
|
||||
_downloadFileOp = _fileSystem.DownloadFileAsync(options);
|
||||
_downloadFileOp.StartOperation();
|
||||
AddChildOperation(_downloadFileOp);
|
||||
}
|
||||
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadCacheAssetBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.AbortDownload)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Abort download file.";
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCacheAssetBundle)
|
||||
{
|
||||
var options = new LoadAssetBundleOptions();
|
||||
options.FileLoadPath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
options.Bundle = _bundle;
|
||||
_loadAssetBundleOp = _fileSystem.LoadAssetBundleFactory.Invoke(_bundle.Encrypted, options);
|
||||
_loadAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_loadAssetBundleOp);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_loadAssetBundleOp.WaitForCompletion();
|
||||
|
||||
_loadAssetBundleOp.UpdateOperation();
|
||||
if (_loadAssetBundleOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadAssetBundleOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
if (_loadAssetBundleOp.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Loaded cache asset bundle is null.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new AssetBundleResult(_fileSystem, _bundle, _loadAssetBundleOp.Result, _loadAssetBundleOp.ManagedStream);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_loadAssetBundleOp is LoadAssetBundleCompleteOperation)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadAssetBundleOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 加载失败,尝试后备加载
|
||||
_steps = ESteps.TryFallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.TryFallback)
|
||||
{
|
||||
var entry = _fileSystem.Cache.GetEntry(_bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
throw new YooInternalException();
|
||||
|
||||
// 注意:当缓存文件的校验等级为Low的时候,并不能保证缓存文件的完整性。
|
||||
// 说明:在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
|
||||
var verifyResult = FileVerifyTools.FileVerify(entry.DataFilePath, _bundle.FileSize, _bundle.FileCRC);
|
||||
if (verifyResult == EFileVerifyResult.Succeed)
|
||||
{
|
||||
// 调用后备加载方法
|
||||
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
|
||||
// 说明:大多数情况在首次安装下载资源到沙盒内,游戏过程中切换到后台再回到游戏内有很大概率触发!
|
||||
AssetBundle assetBundle = _loadAssetBundleOp.LoadFromMemory();
|
||||
if (assetBundle != null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new AssetBundleResult(_fileSystem, _bundle, assetBundle, null);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to load asset bundle from memory : {_bundle.BundleName}";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 文件损坏,删除缓存
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Find corrupted asset bundle file and delete : {_bundle.BundleName}";
|
||||
YooLogger.Error(Error);
|
||||
_fileSystem.Cache.RemoveEntry(_bundle.BundleGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
||||
internal class CFSLoadRawBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExist,
|
||||
DownloadFile,
|
||||
AbortDownload,
|
||||
LoadCacheRawBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
protected readonly CacheFileSystem _fileSystem;
|
||||
protected readonly PackageBundle _bundle;
|
||||
protected FSDownloadFileOperation _downloadFileOp;
|
||||
protected LoadRawBundleOperation _loadRawBundleOp;
|
||||
protected ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal CFSLoadRawBundleOperation(CacheFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckExist;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckExist)
|
||||
{
|
||||
if (_fileSystem.Exists(_bundle))
|
||||
{
|
||||
// 注意:缓存的原生文件的格式,可能会在业务端根据需求发生变动!
|
||||
// 注意:这里需要校验文件格式,如果不一致对本地文件进行修正!
|
||||
var entry = _fileSystem.Cache.GetEntry(_bundle.BundleGUID);
|
||||
if (entry == null)
|
||||
throw new YooInternalException();
|
||||
|
||||
if (File.Exists(entry.DataFilePath) == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
string destFilePath = _fileSystem.Cache.GetDataFilePath(_bundle);
|
||||
entry.MoveFile(destFilePath);
|
||||
_steps = ESteps.LoadCacheRawBundle;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Faild rename cached data file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadCacheRawBundle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.DownloadFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
// 中断下载
|
||||
if (AbortDownloadFile)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
_downloadFileOp.AbortOperation();
|
||||
_steps = ESteps.AbortDownload;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
if (_downloadFileOp == null)
|
||||
{
|
||||
DownloadFileOptions options = new DownloadFileOptions(_bundle, int.MaxValue);
|
||||
_downloadFileOp = _fileSystem.DownloadFileAsync(options);
|
||||
_downloadFileOp.StartOperation();
|
||||
AddChildOperation(_downloadFileOp);
|
||||
}
|
||||
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadCacheRawBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.AbortDownload)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Abort download file.";
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCacheRawBundle)
|
||||
{
|
||||
var options = new LoadRawBundleOptions();
|
||||
options.FileLoadPath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
options.Bundle = _bundle;
|
||||
_loadRawBundleOp = _fileSystem.LoadRawBundleFactory.Invoke(_bundle.Encrypted, options);
|
||||
_loadRawBundleOp.StartOperation();
|
||||
AddChildOperation(_loadRawBundleOp);
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_loadRawBundleOp.WaitForCompletion();
|
||||
|
||||
_loadRawBundleOp.UpdateOperation();
|
||||
if (_loadRawBundleOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadRawBundleOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
if (_loadRawBundleOp.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Loaded cache raw bundle is null.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new RawBundleResult(_fileSystem, _bundle, _loadRawBundleOp.Result);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadRawBundleOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a653cabf995909d48935a0486db6116f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,166 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CFSLoadPackageManifestOperation : FSLoadManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
DownloadPackageHash,
|
||||
DownloadPackageManifest,
|
||||
LoadCachePackageHash,
|
||||
LoadCachePackageManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private DownloadPackageHashOperation _downloadPackageHashOp;
|
||||
private DownloadPackageManifestOperation _downloadPackageManifestOp;
|
||||
private LoadCachePackageHashOperation _loadCachePackageHashOp;
|
||||
private LoadCachePackageManifestOperation _loadCachePackageManifestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal CFSLoadPackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.DownloadPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.DownloadPackageHash)
|
||||
{
|
||||
if (_downloadPackageHashOp == null)
|
||||
{
|
||||
_downloadPackageHashOp = new DownloadPackageHashOperation(_fileSystem, _packageVersion, _timeout);
|
||||
_downloadPackageHashOp.StartOperation();
|
||||
AddChildOperation(_downloadPackageHashOp);
|
||||
}
|
||||
|
||||
_downloadPackageHashOp.UpdateOperation();
|
||||
if (_downloadPackageHashOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadPackageHashOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.DownloadPackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadPackageHashOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadPackageManifest)
|
||||
{
|
||||
if (_downloadPackageManifestOp == null)
|
||||
{
|
||||
_downloadPackageManifestOp = new DownloadPackageManifestOperation(_fileSystem, _packageVersion, _timeout);
|
||||
_downloadPackageManifestOp.StartOperation();
|
||||
AddChildOperation(_downloadPackageManifestOp);
|
||||
}
|
||||
|
||||
_downloadPackageManifestOp.UpdateOperation();
|
||||
if (_downloadPackageManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadPackageManifestOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadCachePackageHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadPackageManifestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCachePackageHash)
|
||||
{
|
||||
if (_loadCachePackageHashOp == null)
|
||||
{
|
||||
_loadCachePackageHashOp = new LoadCachePackageHashOperation(_fileSystem, _packageVersion);
|
||||
_loadCachePackageHashOp.StartOperation();
|
||||
AddChildOperation(_loadCachePackageHashOp);
|
||||
}
|
||||
|
||||
_loadCachePackageHashOp.UpdateOperation();
|
||||
if (_loadCachePackageHashOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadCachePackageHashOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadCachePackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadCachePackageHashOp.Error;
|
||||
ClearCacheFatalFile();
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCachePackageManifest)
|
||||
{
|
||||
if (_loadCachePackageManifestOp == null)
|
||||
{
|
||||
string packageHash = _loadCachePackageHashOp.PackageHash;
|
||||
_loadCachePackageManifestOp = new LoadCachePackageManifestOperation(_fileSystem, _packageVersion, packageHash);
|
||||
_loadCachePackageManifestOp.StartOperation();
|
||||
AddChildOperation(_loadCachePackageManifestOp);
|
||||
}
|
||||
|
||||
_loadCachePackageManifestOp.UpdateOperation();
|
||||
Progress = _loadCachePackageManifestOp.Progress;
|
||||
if (_loadCachePackageManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadCachePackageManifestOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _loadCachePackageManifestOp.Manifest;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadCachePackageManifestOp.Error;
|
||||
ClearCacheFatalFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearCacheFatalFile()
|
||||
{
|
||||
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,主动把损坏的文件删除。
|
||||
string manifestFilePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||
if (File.Exists(manifestFilePath))
|
||||
{
|
||||
YooLogger.Warning($"Invalid cache manifest file have been removed : {manifestFilePath}");
|
||||
File.Delete(manifestFilePath);
|
||||
}
|
||||
|
||||
string hashFilePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||
if (File.Exists(hashFilePath))
|
||||
{
|
||||
File.Delete(hashFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2447826454481704ab785153ae89be3a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CFSRequestPackageVersionOperation : FSRequestVersionOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetPackageVersion,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly bool _appendTimeTicks;
|
||||
private readonly int _timeout;
|
||||
private RequestRemotePackageVersionOperation _requestRemotePackageVersionOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal CFSRequestPackageVersionOperation(CacheFileSystem fileSystem, bool appendTimeTicks, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_appendTimeTicks = appendTimeTicks;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.GetPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetPackageVersion)
|
||||
{
|
||||
if (_requestRemotePackageVersionOp == null)
|
||||
{
|
||||
_requestRemotePackageVersionOp = new RequestRemotePackageVersionOperation(_fileSystem, _appendTimeTicks, _timeout);
|
||||
_requestRemotePackageVersionOp.StartOperation();
|
||||
AddChildOperation(_requestRemotePackageVersionOp);
|
||||
}
|
||||
|
||||
_requestRemotePackageVersionOp.UpdateOperation();
|
||||
Progress = _requestRemotePackageVersionOp.Progress;
|
||||
if (_requestRemotePackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestRemotePackageVersionOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
PackageVersion = _requestRemotePackageVersionOp.PackageVersion;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestRemotePackageVersionOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 856b1334d67ed4d41b31a583f713c449
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3414bfb159816a74f917270b7d48c25f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearAllCacheBundleFilesOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
ClearCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private FCClearCacheOperation _clearCacheFileOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearAllCacheBundleFilesOperation(CacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.ClearCacheFiles;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.ClearCacheFiles)
|
||||
{
|
||||
if (_clearCacheFileOp == null)
|
||||
{
|
||||
var options = new FCClearCacheOptions();
|
||||
options.BundleGUIDs = GetRemoveFiles();
|
||||
_clearCacheFileOp = _fileSystem.Cache.ClearCacheAsync(options);
|
||||
_clearCacheFileOp.StartOperation();
|
||||
AddChildOperation(_clearCacheFileOp);
|
||||
}
|
||||
|
||||
_clearCacheFileOp.UpdateOperation();
|
||||
Progress = _clearCacheFileOp.Progress;
|
||||
if (_clearCacheFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_clearCacheFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _clearCacheFileOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetRemoveFiles()
|
||||
{
|
||||
var allEntrys = _fileSystem.Cache.GetAllEntries();
|
||||
List<string> result = new List<string>(allEntrys.Count);
|
||||
foreach (var entry in allEntrys)
|
||||
{
|
||||
result.Add(entry.BundleGUID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: daed187502431d347bf11bddcf8d77de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearAllCacheManifestFilesOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
ClearAllCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearAllCacheManifestFilesOperation(CacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.ClearAllCacheFiles;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.ClearAllCacheFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 注意:如果正在下载资源清单,会有几率触发异常!
|
||||
string directoryRoot = _fileSystem.GetCacheManifestFilesRoot();
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot);
|
||||
if (directoryInfo.Exists)
|
||||
{
|
||||
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
|
||||
{
|
||||
string fileName = fileInfo.Name;
|
||||
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName)
|
||||
continue;
|
||||
|
||||
fileInfo.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Error = ex.Message;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5643382e7031ba14cbb4ab0f4a9acd94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,136 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class ClearCacheBundleFilesByLocationsOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckManifest,
|
||||
CheckArgs,
|
||||
ClearCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private readonly object _clearParam;
|
||||
private FCClearCacheOperation _clearCacheFileOp;
|
||||
private string[] _locations;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearCacheBundleFilesByLocationsOperation(CacheFileSystem fileSystem, PackageManifest manifest, object clearParam)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
_clearParam = clearParam;
|
||||
}
|
||||
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckManifest;
|
||||
}
|
||||
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckManifest)
|
||||
{
|
||||
if (_manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Can not found active package manifest.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckArgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckArgs)
|
||||
{
|
||||
if (_clearParam == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Clear param is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clearParam is string)
|
||||
{
|
||||
_locations = new string[] { _clearParam as string };
|
||||
}
|
||||
else if (_clearParam is List<string>)
|
||||
{
|
||||
var tempList = _clearParam as List<string>;
|
||||
_locations = tempList.ToArray();
|
||||
}
|
||||
else if (_clearParam is string[])
|
||||
{
|
||||
_locations = _clearParam as string[];
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Invalid clear param : {_clearParam.GetType().FullName}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.ClearCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearCacheFiles)
|
||||
{
|
||||
if (_clearCacheFileOp == null)
|
||||
{
|
||||
var options = new FCClearCacheOptions();
|
||||
options.BundleGUIDs = GetRemoveFiles();
|
||||
_clearCacheFileOp = _fileSystem.Cache.ClearCacheAsync(options);
|
||||
_clearCacheFileOp.StartOperation();
|
||||
AddChildOperation(_clearCacheFileOp);
|
||||
}
|
||||
|
||||
_clearCacheFileOp.UpdateOperation();
|
||||
Progress = _clearCacheFileOp.Progress;
|
||||
if (_clearCacheFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_clearCacheFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _clearCacheFileOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetRemoveFiles()
|
||||
{
|
||||
List<string> result = new List<string>(_locations.Length);
|
||||
foreach (var location in _locations)
|
||||
{
|
||||
string assetPath = _manifest.TryMappingToAssetPath(location);
|
||||
if (_manifest.TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
PackageBundle bundle = _manifest.GetMainPackageBundle(packageAsset.BundleID);
|
||||
if (bundle != null)
|
||||
{
|
||||
result.Add(bundle.BundleGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0be6ffd570645bf4a95126958a8e8a86
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class ClearCacheBundleFilesByTagsOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckManifest,
|
||||
CheckArgs,
|
||||
ClearCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private readonly object _clearParam;
|
||||
private FCClearCacheOperation _clearCacheFileOp;
|
||||
private string[] _tags;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearCacheBundleFilesByTagsOperation(CacheFileSystem fileSystem, PackageManifest manifest, object clearParam)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
_clearParam = clearParam;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckManifest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckManifest)
|
||||
{
|
||||
if (_manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Can not found active package manifest.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckArgs;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckArgs)
|
||||
{
|
||||
if (_clearParam == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Clear param is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clearParam is string)
|
||||
{
|
||||
_tags = new string[] { _clearParam as string };
|
||||
}
|
||||
else if (_clearParam is List<string>)
|
||||
{
|
||||
var tempList = _clearParam as List<string>;
|
||||
_tags = tempList.ToArray();
|
||||
}
|
||||
else if (_clearParam is string[])
|
||||
{
|
||||
_tags = _clearParam as string[];
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Invalid clear param : {_clearParam.GetType().FullName}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.ClearCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearCacheFiles)
|
||||
{
|
||||
if (_clearCacheFileOp == null)
|
||||
{
|
||||
var options = new FCClearCacheOptions();
|
||||
options.BundleGUIDs = GetRemoveFiles();
|
||||
_clearCacheFileOp = _fileSystem.Cache.ClearCacheAsync(options);
|
||||
_clearCacheFileOp.StartOperation();
|
||||
AddChildOperation(_clearCacheFileOp);
|
||||
}
|
||||
|
||||
_clearCacheFileOp.UpdateOperation();
|
||||
Progress = _clearCacheFileOp.Progress;
|
||||
if (_clearCacheFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_clearCacheFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _clearCacheFileOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
private List<string> GetRemoveFiles()
|
||||
{
|
||||
var allEntrys = _fileSystem.Cache.GetAllEntries();
|
||||
List<string> result = new List<string>(allEntrys.Count);
|
||||
foreach (var entry in allEntrys)
|
||||
{
|
||||
if (_manifest.TryGetPackageBundleByBundleGUID(entry.BundleGUID, out PackageBundle bundle))
|
||||
{
|
||||
if (bundle.HasTag(_tags))
|
||||
{
|
||||
result.Add(bundle.BundleGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c42345c14a903274fb160a813ee174dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearUnusedCacheBundleFilesOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckManifest,
|
||||
ClearCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private FCClearCacheOperation _clearCacheFileOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearUnusedCacheBundleFilesOperation(CacheFileSystem fileSystem, PackageManifest manifest)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckManifest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckManifest)
|
||||
{
|
||||
if (_manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Can not found active package manifest.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.ClearCacheFiles;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearCacheFiles)
|
||||
{
|
||||
if (_clearCacheFileOp == null)
|
||||
{
|
||||
var options = new FCClearCacheOptions();
|
||||
options.BundleGUIDs = GetRemoveFiles();
|
||||
_clearCacheFileOp = _fileSystem.Cache.ClearCacheAsync(options);
|
||||
_clearCacheFileOp.StartOperation();
|
||||
AddChildOperation(_clearCacheFileOp);
|
||||
}
|
||||
|
||||
_clearCacheFileOp.UpdateOperation();
|
||||
Progress = _clearCacheFileOp.Progress;
|
||||
if (_clearCacheFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_clearCacheFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _clearCacheFileOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
private List<string> GetRemoveFiles()
|
||||
{
|
||||
var allEntrys = _fileSystem.Cache.GetAllEntries();
|
||||
List<string> result = new List<string>(allEntrys.Count);
|
||||
foreach (var entry in allEntrys)
|
||||
{
|
||||
if (_manifest.IsIncludeBundleFile(entry.BundleGUID) == false)
|
||||
{
|
||||
result.Add(entry.BundleGUID);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be7b242f10abf524fa59e9ca0d12b052
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearUnusedCacheManifestFilesOperation : FSClearCacheOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckManifest,
|
||||
ClearUnusedCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearUnusedCacheManifestFilesOperation(CacheFileSystem fileSystem, PackageManifest manifest)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckManifest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckManifest)
|
||||
{
|
||||
if (_manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Can not found active package manifest.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.ClearUnusedCacheFiles;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
string activeManifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(_manifest.PackageName, _manifest.PackageVersion);
|
||||
string activeHashFileName = YooAssetSettingsData.GetPackageHashFileName(_manifest.PackageName, _manifest.PackageVersion);
|
||||
|
||||
// 注意:如果正在下载资源清单,会有几率触发异常!
|
||||
string directoryRoot = _fileSystem.GetCacheManifestFilesRoot();
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot);
|
||||
if (directoryInfo.Exists)
|
||||
{
|
||||
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
|
||||
{
|
||||
string fileName = fileInfo.Name;
|
||||
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName)
|
||||
continue;
|
||||
if (fileName == activeManifestFileName || fileName == activeHashFileName)
|
||||
continue;
|
||||
|
||||
fileInfo.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Error = ex.Message;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d911513cf97d862448df570f0c8e9b38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,154 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadPackageBundleOperation : FSDownloadFileOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExists,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
TryAgain,
|
||||
Done,
|
||||
}
|
||||
|
||||
// 下载参数
|
||||
protected readonly CacheFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
private DownloadAndCacheFileOperation _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer = 0;
|
||||
protected int _failedTryAgain;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal DownloadPackageBundleOperation(CacheFileSystem fileSystem, DownloadFileOptions options) : base(options.Bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_options = options;
|
||||
_failedTryAgain = options.FailedTryAgain;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckExists;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 检测文件是否存在
|
||||
if (_steps == ESteps.CheckExists)
|
||||
{
|
||||
if (_fileSystem.Exists(Bundle))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
if (_options.IsValid() == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Download file options is invalid.";
|
||||
Debug.Log(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
string url = GetRequestURL();
|
||||
_downloadFileOp = _fileSystem.DownloadScheduler.DownloadAndCacheFileAsync(Bundle, url);
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
Progress = _downloadFileOp.Progress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsWaitForCompletion == false && _failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_downloadFileOp.URL} Try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadFileOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
_tryAgainTimer = 0f;
|
||||
_failedTryAgain--;
|
||||
Progress = 0f;
|
||||
DownloadProgress = 0f;
|
||||
DownloadedBytes = 0;
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
// 注意:取消下载任务的时候引用计数减一
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
{
|
||||
_downloadFileOp.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络请求地址
|
||||
/// </summary>
|
||||
protected string GetRequestURL()
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
_requestCount++;
|
||||
if (_requestCount % 2 == 0)
|
||||
return _options.FallbackURL;
|
||||
else
|
||||
return _options.MainURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af07b7cdf729e944dbb6d60204c71235
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadPackageHashOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExist,
|
||||
DownloadFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal DownloadPackageHashOperation(CacheFileSystem fileSystem, string packageVersion, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_requestCount = DownloadFailureCounter.GetFailureCount(_fileSystem.PackageName, nameof(DownloadPackageHashOperation));
|
||||
_steps = ESteps.CheckExist;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckExist)
|
||||
{
|
||||
string filePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.DownloadFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
if (_webFileRequestOp == null)
|
||||
{
|
||||
string savePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
|
||||
string webURL = GetWebRequestURL(fileName);
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webFileRequestOp.Error;
|
||||
DownloadFailureCounter.RecordFailure(_fileSystem.PackageName, nameof(DownloadPackageHashOperation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetWebRequestURL(string fileName)
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
if (_requestCount % 2 == 0)
|
||||
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
|
||||
else
|
||||
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8604af2bf2c8a1d4684cb59d81ab9445
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadPackageManifestOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExist,
|
||||
DownloadFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private IDownloadFileRequest _webFileRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal DownloadPackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_requestCount = DownloadFailureCounter.GetFailureCount(_fileSystem.PackageName, nameof(DownloadPackageManifestOperation));
|
||||
_steps = ESteps.CheckExist;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckExist)
|
||||
{
|
||||
string filePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.DownloadFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
if (_webFileRequestOp == null)
|
||||
{
|
||||
string savePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
|
||||
string webURL = GetDownloadRequestURL(fileName);
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
var args = new DownloadFileRequestArgs(webURL, savePath, _timeout, watchdogTime);
|
||||
_webFileRequestOp = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_webFileRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
if (_webFileRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webFileRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webFileRequestOp.Error;
|
||||
DownloadFailureCounter.RecordFailure(_fileSystem.PackageName, nameof(DownloadPackageManifestOperation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDownloadRequestURL(string fileName)
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
if (_requestCount % 2 == 0)
|
||||
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
|
||||
else
|
||||
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d5983f1b32b2e14c8b4c5b539bee8fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class LoadCachePackageHashOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadPackageHash,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹哈希值
|
||||
/// </summary>
|
||||
public string PackageHash { private set; get; }
|
||||
|
||||
|
||||
internal LoadCachePackageHashOperation(CacheFileSystem fileSystem, string packageVersion)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadPackageHash)
|
||||
{
|
||||
string filePath = _fileSystem.GetCachePackageHashFilePath(_packageVersion);
|
||||
if (File.Exists(filePath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Can not found cache package hash file : {filePath}";
|
||||
return;
|
||||
}
|
||||
|
||||
PackageHash = FileUtility.ReadAllText(filePath);
|
||||
if (string.IsNullOrEmpty(PackageHash))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Cache package hash file content is empty.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db66f75d31bfeca4e897e9ee0946b1de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class LoadCachePackageManifestOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadFileData,
|
||||
VerifyFileData,
|
||||
LoadManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly string _packageHash;
|
||||
private DeserializeManifestOperation _deserializer;
|
||||
private byte[] _fileData;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹清单
|
||||
/// </summary>
|
||||
public PackageManifest Manifest { private set; get; }
|
||||
|
||||
|
||||
internal LoadCachePackageManifestOperation(CacheFileSystem fileSystem, string packageVersion, string packageHash)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_packageHash = packageHash;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadFileData;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadFileData)
|
||||
{
|
||||
string manifestFilePath = _fileSystem.GetCachePackageManifestFilePath(_packageVersion);
|
||||
if (File.Exists(manifestFilePath))
|
||||
{
|
||||
_steps = ESteps.VerifyFileData;
|
||||
_fileData = File.ReadAllBytes(manifestFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Can not found cache manifest file : {manifestFilePath}";
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyFileData)
|
||||
{
|
||||
if (PackageManifestTools.VerifyManifestData(_fileData, _packageHash))
|
||||
{
|
||||
_steps = ESteps.LoadManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Failed to verify cache package manifest file.";
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadManifest)
|
||||
{
|
||||
if (_deserializer == null)
|
||||
{
|
||||
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestRestoreServices, _fileData);
|
||||
_deserializer.StartOperation();
|
||||
AddChildOperation(_deserializer);
|
||||
}
|
||||
|
||||
_deserializer.UpdateOperation();
|
||||
Progress = _deserializer.Progress;
|
||||
if (_deserializer.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_deserializer.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _deserializer.Manifest;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _deserializer.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
return $"PackageVersion : {_packageVersion} PackageHash : {_packageHash}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acd84795f7cc3e348ab2b6cde03c8a22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RequestRemotePackageVersionOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
RequestPackageVersion,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly bool _appendTimeTicks;
|
||||
private readonly int _timeout;
|
||||
private IDownloadTextRequest _webTextRequestOp;
|
||||
private int _requestCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹版本
|
||||
/// </summary>
|
||||
internal string PackageVersion { set; get; }
|
||||
|
||||
|
||||
internal RequestRemotePackageVersionOperation(CacheFileSystem fileSystem, bool appendTimeTicks, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_appendTimeTicks = appendTimeTicks;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_requestCount = DownloadFailureCounter.GetFailureCount(_fileSystem.PackageName, nameof(RequestRemotePackageVersionOperation));
|
||||
_steps = ESteps.RequestPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.RequestPackageVersion)
|
||||
{
|
||||
if (_webTextRequestOp == null)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
|
||||
string url = GetWebRequestURL(fileName);
|
||||
int watchDogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
var args = new DownloadDataRequestArgs(url, _timeout, watchDogTime);
|
||||
_webTextRequestOp = _fileSystem.DownloadBackend.CreateTextRequest(args);
|
||||
_webTextRequestOp.SendRequest();
|
||||
}
|
||||
|
||||
Progress = _webTextRequestOp.DownloadProgress;
|
||||
if (_webTextRequestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
PackageVersion = _webTextRequestOp.Result;
|
||||
if (string.IsNullOrEmpty(PackageVersion))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Remote package version file content is empty.";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _webTextRequestOp.Error;
|
||||
DownloadFailureCounter.RecordFailure(_fileSystem.PackageName, nameof(RequestRemotePackageVersionOperation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetWebRequestURL(string fileName)
|
||||
{
|
||||
string url;
|
||||
|
||||
// 轮流返回请求地址
|
||||
if (_requestCount % 2 == 0)
|
||||
url = _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
|
||||
else
|
||||
url = _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||
|
||||
// 在URL末尾添加时间戳
|
||||
if (_appendTimeTicks)
|
||||
return $"{url}?{System.DateTime.UtcNow.Ticks}";
|
||||
else
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b078a220cc4f7d4392d77ccc77c001e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf9991076b60f0f459846f54b0ca6698
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class DownloadAndCacheFileOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载地址
|
||||
/// </summary>
|
||||
public readonly string URL;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
/// </summary>
|
||||
public float DownloadProgress { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载字节
|
||||
/// </summary>
|
||||
public long DownloadedBytes { get; protected set; }
|
||||
|
||||
public DownloadAndCacheFileOperation(string url)
|
||||
{
|
||||
URL = url;
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
return $"RefCount : {RefCount}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 减少引用计数
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
RefCount--;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加引用计数
|
||||
/// </summary>
|
||||
public void Reference()
|
||||
{
|
||||
RefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2954a64fd419d5a4b9d0a102260d193c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class DownloadAndCacheLocalFileOperation : DownloadAndCacheFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckCopy,
|
||||
CopyLocalFile,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
CacheFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly string _tempFilePath;
|
||||
private IDownloadRequest _request;
|
||||
private FCStoreCacheOperation _bundleCacheOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal DownloadAndCacheLocalFileOperation(CacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(_bundle);
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckCopy;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 检测文件拷贝
|
||||
if (_steps == ESteps.CheckCopy)
|
||||
{
|
||||
// 删除历史缓存文件
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
if (_fileSystem.CopyLocalFileServices != null)
|
||||
_steps = ESteps.CopyLocalFile;
|
||||
else
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
|
||||
// 拷贝本地文件
|
||||
if (_steps == ESteps.CopyLocalFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO 团结引擎,在某些机型(红米),拷贝包内文件会小概率失败!需要借助其它方式来拷贝包内文件。
|
||||
var localFileInfo = new LocalFileInfo();
|
||||
localFileInfo.PackageName = _fileSystem.PackageName;
|
||||
localFileInfo.BundleName = _bundle.BundleName;
|
||||
localFileInfo.SourceFileURL = URL;
|
||||
_fileSystem.CopyLocalFileServices.CopyFile(localFileInfo, _tempFilePath);
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.CacheFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed copy local file : {URL}";
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed copy local file : {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载请求
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime);
|
||||
_request = _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
//TODO 更新下载后台,防止无限挂起
|
||||
if (IsWaitForCompletion)
|
||||
_fileSystem.DownloadBackend.Update();
|
||||
|
||||
DownloadProgress = _request.DownloadProgress;
|
||||
DownloadedBytes = _request.DownloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_request.IsDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_request.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.CacheFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _request.Error;
|
||||
}
|
||||
|
||||
// 最终释放请求器
|
||||
_request.Dispose();
|
||||
}
|
||||
|
||||
// 缓存文件
|
||||
if (_steps == ESteps.CacheFile)
|
||||
{
|
||||
if (_bundleCacheOp == null)
|
||||
{
|
||||
var options = new FCStoreCacheOptions();
|
||||
options.Bundle = _bundle;
|
||||
options.FilePath = _tempFilePath;
|
||||
_bundleCacheOp = _fileSystem.Cache.StoreCacheAsync(options);
|
||||
_bundleCacheOp.StartOperation();
|
||||
AddChildOperation(_bundleCacheOp);
|
||||
}
|
||||
|
||||
if (IsWaitForCompletion)
|
||||
_bundleCacheOp.WaitForCompletion();
|
||||
|
||||
_bundleCacheOp.UpdateOperation();
|
||||
if (_bundleCacheOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_bundleCacheOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _bundleCacheOp.Error;
|
||||
}
|
||||
|
||||
// 注意:缓存完成后直接删除临时文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
if (_request != null)
|
||||
_request.Dispose();
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
//TODO 等待导入或解压本地文件完毕,该操作会挂起主线程!
|
||||
ExecuteUntilComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47700ac672942834f8d5a7c59783d88e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,185 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class DownloadAndCacheRemoteFileOperation : DownloadAndCacheFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
CacheFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private readonly string _tempFilePath;
|
||||
private bool _enableResume = false;
|
||||
private long _fileOriginLength = 0;
|
||||
private IDownloadRequest _request;
|
||||
private FCStoreCacheOperation _bundleCacheOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal DownloadAndCacheRemoteFileOperation(CacheFileSystem fileSystem, PackageBundle bundle, string url) : base(url)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(_bundle);
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 创建下载请求
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
|
||||
_enableResume = _bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize;
|
||||
if (_enableResume)
|
||||
{
|
||||
_request = CreateResumeRequest();
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_request = CreateNormalRequest();
|
||||
_request.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _request.DownloadProgress;
|
||||
DownloadedBytes = _fileOriginLength + _request.DownloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_request.IsDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
if (_request.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.CacheFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _request.Error;
|
||||
}
|
||||
|
||||
// 在遇到特殊错误的时候删除文件
|
||||
if (_enableResume)
|
||||
ClearTempFileWhenError(_request.HttpCode);
|
||||
|
||||
// 最终释放请求器
|
||||
_request.Dispose();
|
||||
}
|
||||
|
||||
// 缓存文件
|
||||
if (_steps == ESteps.CacheFile)
|
||||
{
|
||||
if (_bundleCacheOp == null)
|
||||
{
|
||||
var options = new FCStoreCacheOptions();
|
||||
options.Bundle = _bundle;
|
||||
options.FilePath = _tempFilePath;
|
||||
_bundleCacheOp = _fileSystem.Cache.StoreCacheAsync(options);
|
||||
_bundleCacheOp.StartOperation();
|
||||
AddChildOperation(_bundleCacheOp);
|
||||
}
|
||||
|
||||
_bundleCacheOp.UpdateOperation();
|
||||
if (_bundleCacheOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_bundleCacheOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _bundleCacheOp.Error;
|
||||
}
|
||||
|
||||
// 注意:缓存完成后直接删除临时文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
if (_request != null)
|
||||
_request.Dispose();
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
// 注意:不中断下载任务,保持后台继续下载
|
||||
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote : {URL}");
|
||||
}
|
||||
}
|
||||
|
||||
private IDownloadRequest CreateResumeRequest()
|
||||
{
|
||||
// 获取下载起始位置
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
if (fileInfo.Length >= _bundle.FileSize)
|
||||
{
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileOriginLength = fileInfo.Length;
|
||||
}
|
||||
}
|
||||
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
bool appendToFile = true;
|
||||
bool removeFileOnAbort = false;
|
||||
long resumeOffset = _fileOriginLength;
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime, appendToFile, removeFileOnAbort, resumeOffset);
|
||||
return _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
}
|
||||
private IDownloadRequest CreateNormalRequest()
|
||||
{
|
||||
// 删除历史缓存文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
int watchdogTime = _fileSystem.DownloadWatchDogTimeout;
|
||||
int timeout = 0; //注意:文件下载不做超时检测
|
||||
var args = new DownloadFileRequestArgs(URL, _tempFilePath, timeout, watchdogTime);
|
||||
return _fileSystem.DownloadBackend.CreateFileRequest(args);
|
||||
}
|
||||
private void ClearTempFileWhenError(long httpCode)
|
||||
{
|
||||
if (_fileSystem.ResumeDownloadResponseCodes == null)
|
||||
return;
|
||||
|
||||
//说明:如果遇到以下错误返回码,验证失败直接删除文件
|
||||
if (_fileSystem.ResumeDownloadResponseCodes.Contains(httpCode))
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad910a81855976e44b4f1f09051910b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载调度器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 管理所有活跃的下载任务,控制并发数量。
|
||||
/// </remarks>
|
||||
internal class DownloadSchedulerOperation : AsyncOperationBase, IDisposable
|
||||
{
|
||||
private readonly CacheFileSystem _fileSystem;
|
||||
private readonly Dictionary<string, DownloadAndCacheFileOperation> _downloaders = new Dictionary<string, DownloadAndCacheFileOperation>(1000);
|
||||
private readonly List<string> _removeList = new List<string>(1000);
|
||||
|
||||
/// <summary>
|
||||
/// 是否已暂停
|
||||
/// </summary>
|
||||
public bool Paused { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 当前活跃的下载任务数
|
||||
/// </summary>
|
||||
public int ActiveDownloadCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前等待中的下载任务数
|
||||
/// </summary>
|
||||
public int PendingDownloadCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _downloaders.Count - ActiveDownloadCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构造下载中心
|
||||
/// </summary>
|
||||
public DownloadSchedulerOperation(CacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
// 驱动下载后台
|
||||
_fileSystem.DownloadBackend.Update();
|
||||
|
||||
// 获取可移除的下载器集合
|
||||
_removeList.Clear();
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
downloader.UpdateOperation();
|
||||
if (downloader.IsDone)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:主动终止引用计数为零的下载任务
|
||||
if (downloader.RefCount <= 0)
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
downloader.AbortOperation();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// 移除下载器
|
||||
foreach (var key in _removeList)
|
||||
{
|
||||
if (_downloaders.TryGetValue(key, out var downloader))
|
||||
{
|
||||
RemoveChildOperation(downloader);
|
||||
_downloaders.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 暂停时不启动新任务
|
||||
if (Paused)
|
||||
return;
|
||||
|
||||
// 最大并发数检测
|
||||
ActiveDownloadCount = GetProcessingOperationCount();
|
||||
if (ActiveDownloadCount != _downloaders.Count)
|
||||
{
|
||||
int maxConcurrency = _fileSystem.DownloadMaxConcurrency;
|
||||
int maxRequestPerFrame = _fileSystem.DownloadMaxRequestPerFrame;
|
||||
if (ActiveDownloadCount < maxConcurrency)
|
||||
{
|
||||
int startCount = maxConcurrency - ActiveDownloadCount;
|
||||
if (startCount > maxRequestPerFrame)
|
||||
startCount = maxRequestPerFrame;
|
||||
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status == EOperationStatus.None)
|
||||
{
|
||||
operation.StartOperation();
|
||||
startCount--;
|
||||
if (startCount <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override string InternalGetDescription()
|
||||
{
|
||||
return $"{_fileSystem.GetType().FullName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放下载资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var operation = valuePair.Value;
|
||||
operation.AbortOperation();
|
||||
}
|
||||
_downloaders.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下载任务
|
||||
/// </summary>
|
||||
/// <param name="bundle">资源包信息</param>
|
||||
/// <param name="url">下载地址</param>
|
||||
/// <returns>下载操作</returns>
|
||||
public DownloadAndCacheFileOperation DownloadAndCacheFileAsync(PackageBundle bundle, string url)
|
||||
{
|
||||
// 查询旧的下载器
|
||||
if (_downloaders.TryGetValue(bundle.BundleGUID, out var oldDownloader))
|
||||
{
|
||||
oldDownloader.Reference();
|
||||
return oldDownloader;
|
||||
}
|
||||
|
||||
// 创建新的下载器
|
||||
DownloadAndCacheFileOperation newDownloader;
|
||||
bool isRequestLocalFile = DownloadSystemTools.IsLocalFileURL(url);
|
||||
if (isRequestLocalFile)
|
||||
{
|
||||
newDownloader = new DownloadAndCacheLocalFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDownloader = new DownloadAndCacheRemoteFileOperation(_fileSystem, bundle, url);
|
||||
}
|
||||
|
||||
AddChildOperation(newDownloader);
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
newDownloader.Reference();
|
||||
return newDownloader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取正在进行中的下载器总数
|
||||
/// </summary>
|
||||
private int GetProcessingOperationCount()
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var operationPair in _downloaders)
|
||||
{
|
||||
var operation = operationPair.Value;
|
||||
if (operation.Status != EOperationStatus.None)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73441e829c36a36418f5d677e189e9f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca2dc2186da7a2847b300c398600e472
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,252 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 模拟文件系统
|
||||
/// </summary>
|
||||
internal class EditorFileSystem : IFileSystem
|
||||
{
|
||||
protected readonly Dictionary<string, string> _records = new Dictionary<string, string>(10000);
|
||||
protected string _packageRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 下载后台接口
|
||||
/// </summary>
|
||||
public IDownloadBackend DownloadBackend { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件根目录
|
||||
/// </summary>
|
||||
public string FileRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
return _packageRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件数量
|
||||
/// </summary>
|
||||
public int FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region 自定义参数
|
||||
/// <summary>
|
||||
/// 自定义参数:UnityWebRequest 创建委托
|
||||
/// </summary>
|
||||
public UnityWebRequestCreator WebRequestCreator { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 模拟WebGL平台模式
|
||||
/// </summary>
|
||||
public bool VirtualWebGLMode { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟虚拟下载模式
|
||||
/// </summary>
|
||||
public bool VirtualDownloadMode { private set; get; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 模拟虚拟下载的网速(单位:字节)
|
||||
/// </summary>
|
||||
public int VirtualDownloadSpeed { private set; get; } = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// 异步模拟加载最小帧数
|
||||
/// </summary>
|
||||
public int AsyncSimulateMinFrame { private set; get; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 异步模拟加载最大帧数
|
||||
/// </summary>
|
||||
public int AsyncSimulateMaxFrame { private set; get; } = 1;
|
||||
#endregion
|
||||
|
||||
public EditorFileSystem()
|
||||
{
|
||||
}
|
||||
public virtual FSInitializeOperation InitializeAsync()
|
||||
{
|
||||
var operation = new EFSInitializeOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSRequestVersionOperation RequestVersionAsync(RequestVersionOptions options)
|
||||
{
|
||||
var operation = new EFSRequestVersionOperation(this);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSLoadManifestOperation LoadManifestAsync(LoadManifestOptions options)
|
||||
{
|
||||
var operation = new EFSLoadManifestOperation(this, options.PackageVersion);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSClearCacheOperation ClearCacheAsync(ClearCacheOptions options)
|
||||
{
|
||||
var operation = new FSClearCacheCompleteOperation();
|
||||
return operation;
|
||||
}
|
||||
public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options)
|
||||
{
|
||||
string mainURL = options.Bundle.BundleName;
|
||||
options.SetURL(mainURL, mainURL);
|
||||
var downloader = new DownloadVirtualBundleOperation(this, options);
|
||||
return downloader;
|
||||
}
|
||||
public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
||||
{
|
||||
PackageBundle bundle = options.Bundle;
|
||||
if (bundle.BundleType == (int)EBundleType.VirtualBundle)
|
||||
{
|
||||
var operation = new EFSLoadBundleOperation(this, bundle);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = $"{nameof(EditorFileSystem)} not support load bundle type : {bundle.BundleType}";
|
||||
var operation = new FSLoadBundleCompleteOperation(error);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetParameter(string name, object value)
|
||||
{
|
||||
if (name == FileSystemParametersDefine.DOWNLOAD_BACKEND)
|
||||
{
|
||||
DownloadBackend = (IDownloadBackend)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.UNITY_WEB_REQUEST_CREATOR)
|
||||
{
|
||||
WebRequestCreator = (UnityWebRequestCreator)value;
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.VIRTUAL_WEBGL_MODE)
|
||||
{
|
||||
VirtualWebGLMode = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.VIRTUAL_DOWNLOAD_MODE)
|
||||
{
|
||||
VirtualDownloadMode = Convert.ToBoolean(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.VIRTUAL_DOWNLOAD_SPEED)
|
||||
{
|
||||
VirtualDownloadSpeed = Convert.ToInt32(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.ASYNC_SIMULATE_MIN_FRAME)
|
||||
{
|
||||
AsyncSimulateMinFrame = Convert.ToInt32(value);
|
||||
}
|
||||
else if (name == FileSystemParametersDefine.ASYNC_SIMULATE_MAX_FRAME)
|
||||
{
|
||||
AsyncSimulateMaxFrame = Convert.ToInt32(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning($"Invalid parameter : {name}");
|
||||
}
|
||||
}
|
||||
public virtual void OnCreate(string packageName, string packageRoot)
|
||||
{
|
||||
PackageName = packageName;
|
||||
|
||||
if (string.IsNullOrEmpty(packageRoot))
|
||||
throw new YooFileSystemException($"{nameof(EditorFileSystem)} package root is null or empty.");
|
||||
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
// 创建默认的下载后台接口
|
||||
if (DownloadBackend == null)
|
||||
DownloadBackend = new UnityWebRequestBackend(WebRequestCreator);
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (DownloadBackend != null)
|
||||
{
|
||||
DownloadBackend.Dispose();
|
||||
DownloadBackend = null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Belong(PackageBundle bundle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool Exists(PackageBundle bundle)
|
||||
{
|
||||
if (VirtualDownloadMode)
|
||||
{
|
||||
return _records.ContainsKey(bundle.BundleGUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public virtual bool NeedDownload(PackageBundle bundle)
|
||||
{
|
||||
if (Belong(bundle) == false)
|
||||
return false;
|
||||
|
||||
return Exists(bundle) == false;
|
||||
}
|
||||
public virtual bool NeedUnpack(PackageBundle bundle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual bool NeedImport(PackageBundle bundle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual string GetBundleFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (bundle.IncludeMainAssets.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var pacakgeAsset = bundle.IncludeMainAssets[0];
|
||||
return pacakgeAsset.AssetPath;
|
||||
}
|
||||
|
||||
#region 内部方法
|
||||
public void RecordDownloadFile(PackageBundle bundle)
|
||||
{
|
||||
if (_records.ContainsKey(bundle.BundleGUID) == false)
|
||||
_records.Add(bundle.BundleGUID, bundle.BundleName);
|
||||
}
|
||||
public string GetEditorPackageVersionFilePath()
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public string GetEditorPackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public string GetEditorPackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_packageRoot, fileName);
|
||||
}
|
||||
public int GetAsyncSimulateFrame()
|
||||
{
|
||||
if (AsyncSimulateMinFrame > AsyncSimulateMaxFrame)
|
||||
{
|
||||
AsyncSimulateMinFrame = AsyncSimulateMaxFrame;
|
||||
}
|
||||
|
||||
return UnityEngine.Random.Range(AsyncSimulateMinFrame, AsyncSimulateMaxFrame + 1);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53f40d241c7bcf340841a33459678568
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3779423aa03ffb6499efda626280c72a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFSInitializeOperation : FSInitializeOperation
|
||||
{
|
||||
private readonly EditorFileSystem _fileSytem;
|
||||
|
||||
internal EFSInitializeOperation(EditorFileSystem fileSystem)
|
||||
{
|
||||
_fileSytem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99cfeba8095613442992a0e21a248b73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFSLoadBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExist,
|
||||
DownloadFile,
|
||||
AbortDownload,
|
||||
LoadAssetBundle,
|
||||
CheckResult,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly EditorFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
protected FSDownloadFileOperation _downloadFileOp;
|
||||
private int _asyncSimulateFrame;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal EFSLoadBundleOperation(EditorFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckExist;
|
||||
_asyncSimulateFrame = _fileSystem.GetAsyncSimulateFrame();
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckExist)
|
||||
{
|
||||
if (_fileSystem.Exists(_bundle))
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = _bundle.FileSize;
|
||||
_steps = ESteps.LoadAssetBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.DownloadFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
// 中断下载
|
||||
if (AbortDownloadFile)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
_downloadFileOp.AbortOperation();
|
||||
_steps = ESteps.AbortDownload;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.DownloadFile)
|
||||
{
|
||||
if (_downloadFileOp == null)
|
||||
{
|
||||
DownloadFileOptions options = new DownloadFileOptions(_bundle, int.MaxValue);
|
||||
_downloadFileOp = _fileSystem.DownloadFileAsync(options);
|
||||
_downloadFileOp.StartOperation();
|
||||
AddChildOperation(_downloadFileOp);
|
||||
}
|
||||
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadFileOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadAssetBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadFileOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.AbortDownload)
|
||||
{
|
||||
if (_downloadFileOp != null)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
_downloadFileOp.WaitForCompletion();
|
||||
|
||||
_downloadFileOp.UpdateOperation();
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Abort download file.";
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadAssetBundle)
|
||||
{
|
||||
if (IsWaitForCompletion)
|
||||
{
|
||||
if (_fileSystem.VirtualWebGLMode)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Virtual WebGL Mode only support asyn load method.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_asyncSimulateFrame <= 0)
|
||||
_steps = ESteps.CheckResult;
|
||||
else
|
||||
_asyncSimulateFrame--;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckResult)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new VirtualBundleResult(_fileSystem, _bundle);
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
ExecuteBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47b871368218c7c49920927c10c6955e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFSLoadManifestOperation : FSLoadManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadEditorPackageHash,
|
||||
LoadEditorPackageManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly EditorFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private LoadEditorPackageHashOperation _loadEditorPackageHashOpe;
|
||||
private LoadEditorPackageManifestOperation _loadEditorPackageManifestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal EFSLoadManifestOperation(EditorFileSystem fileSystem, string packageVersion)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadEditorPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadEditorPackageHash)
|
||||
{
|
||||
if (_loadEditorPackageHashOpe == null)
|
||||
{
|
||||
_loadEditorPackageHashOpe = new LoadEditorPackageHashOperation(_fileSystem, _packageVersion);
|
||||
_loadEditorPackageHashOpe.StartOperation();
|
||||
AddChildOperation(_loadEditorPackageHashOpe);
|
||||
}
|
||||
|
||||
_loadEditorPackageHashOpe.UpdateOperation();
|
||||
if (_loadEditorPackageHashOpe.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadEditorPackageHashOpe.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.LoadEditorPackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadEditorPackageHashOpe.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadEditorPackageManifest)
|
||||
{
|
||||
if (_loadEditorPackageManifestOp == null)
|
||||
{
|
||||
string packageHash = _loadEditorPackageHashOpe.PackageHash;
|
||||
_loadEditorPackageManifestOp = new LoadEditorPackageManifestOperation(_fileSystem, _packageVersion, packageHash);
|
||||
_loadEditorPackageManifestOp.StartOperation();
|
||||
AddChildOperation(_loadEditorPackageManifestOp);
|
||||
}
|
||||
|
||||
_loadEditorPackageManifestOp.UpdateOperation();
|
||||
Progress = _loadEditorPackageManifestOp.Progress;
|
||||
if (_loadEditorPackageManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadEditorPackageManifestOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _loadEditorPackageManifestOp.Manifest;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadEditorPackageManifestOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3abaff43b56f62489688162296203cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EFSRequestVersionOperation : FSRequestVersionOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadPackageVersion,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly EditorFileSystem _fileSystem;
|
||||
private LoadEditorPackageVersionOperation _loadEditorPackageVersionOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal EFSRequestVersionOperation(EditorFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.LoadPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadPackageVersion)
|
||||
{
|
||||
if (_loadEditorPackageVersionOp == null)
|
||||
{
|
||||
_loadEditorPackageVersionOp = new LoadEditorPackageVersionOperation(_fileSystem);
|
||||
_loadEditorPackageVersionOp.StartOperation();
|
||||
AddChildOperation(_loadEditorPackageVersionOp);
|
||||
}
|
||||
|
||||
_loadEditorPackageVersionOp.UpdateOperation();
|
||||
if (_loadEditorPackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadEditorPackageVersionOp.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
PackageVersion = _loadEditorPackageVersionOp.PackageVersion;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadEditorPackageVersionOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47293048f9cde3f46a1b297f1c2e3373
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf9de625784f5fe41a8d4fc53bf71ff0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadVirtualBundleOperation : FSDownloadFileOperation
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckExists,
|
||||
CreateRequest,
|
||||
CheckRequest,
|
||||
TryAgain,
|
||||
Done,
|
||||
}
|
||||
|
||||
// 下载参数
|
||||
protected readonly EditorFileSystem _fileSystem;
|
||||
protected readonly DownloadFileOptions _options;
|
||||
protected IDownloadFileRequest _downloadFileOp;
|
||||
|
||||
protected int _requestCount = 0;
|
||||
protected float _tryAgainTimer = 0;
|
||||
protected int _failedTryAgain;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal DownloadVirtualBundleOperation(EditorFileSystem fileSystem, DownloadFileOptions options) : base(options.Bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_options = options;
|
||||
_failedTryAgain = options.FailedTryAgain;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CheckExists;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 检测文件是否存在
|
||||
if (_steps == ESteps.CheckExists)
|
||||
{
|
||||
if (_fileSystem.Exists(Bundle))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
if (_options.IsValid() == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Download file options is invalid.";
|
||||
Debug.Log(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
string url = GetRequestURL();
|
||||
int speed = _fileSystem.VirtualDownloadSpeed;
|
||||
var args = new DownloadSimulateRequestArgs(url, Bundle.FileSize, speed);
|
||||
_downloadFileOp = _fileSystem.DownloadBackend.CreateSimulateRequest(args);
|
||||
_downloadFileOp.SendRequest();
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
Progress = _downloadFileOp.DownloadProgress;
|
||||
DownloadedBytes = _downloadFileOp.DownloadedBytes;
|
||||
DownloadProgress = _downloadFileOp.DownloadProgress;
|
||||
if (_downloadFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadFileOp.Status == EDownloadRequestStatus.Succeed)
|
||||
{
|
||||
_fileSystem.RecordDownloadFile(Bundle);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsWaitForCompletion == false && _failedTryAgain > 0)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
YooLogger.Warning($"Failed download : {_downloadFileOp.URL} Try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadFileOp.Error;
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
_tryAgainTimer = 0f;
|
||||
_failedTryAgain--;
|
||||
Progress = 0f;
|
||||
DownloadProgress = 0f;
|
||||
DownloadedBytes = 0;
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForCompletion()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Try load bundle {Bundle.BundleName} from remote.";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络请求地址
|
||||
/// </summary>
|
||||
protected string GetRequestURL()
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
_requestCount++;
|
||||
if (_requestCount % 2 == 0)
|
||||
return _options.FallbackURL;
|
||||
else
|
||||
return _options.MainURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f043dc0e0f147334380cfd0720636544
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user