mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-27 11:10:11 +00:00
refactor : 代码重构
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -70,6 +70,7 @@ sysinfo.txt
|
|||||||
# Builds
|
# Builds
|
||||||
*.apk
|
*.apk
|
||||||
*.unitypackage
|
*.unitypackage
|
||||||
|
*.zip
|
||||||
|
|
||||||
# Crashlytics generated file
|
# Crashlytics generated file
|
||||||
crashlytics-build.properties
|
crashlytics-build.properties
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件签名(自动填写)
|
/// 文件签名(自动填写)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string FileSign;
|
public string FileSignature;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件版本(自动填写)
|
/// 文件版本(自动填写)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace YooAsset.Editor
|
|||||||
ScanReport report = JsonUtility.FromJson<ScanReport>(jsonData);
|
ScanReport report = JsonUtility.FromJson<ScanReport>(jsonData);
|
||||||
|
|
||||||
// 检测配置文件的签名
|
// 检测配置文件的签名
|
||||||
if (report.FileSign != ScannerDefine.ReportFileSign)
|
if (report.FileSignature != ScannerDefine.ReportFileSign)
|
||||||
throw new Exception($"导入的报告文件无法识别 : {filePath}");
|
throw new Exception($"导入的报告文件无法识别 : {filePath}");
|
||||||
|
|
||||||
// 检测报告文件的版本
|
// 检测报告文件的版本
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace YooAsset.Editor
|
|||||||
throw new Exception($"Failed to load schema : {ScannerSchema}");
|
throw new Exception($"Failed to load schema : {ScannerSchema}");
|
||||||
|
|
||||||
var report = schema.RunScanner(this);
|
var report = schema.RunScanner(this);
|
||||||
report.FileSign = ScannerDefine.ReportFileSign;
|
report.FileSignature = ScannerDefine.ReportFileSign;
|
||||||
report.FileVersion = ScannerDefine.ReportFileVersion;
|
report.FileVersion = ScannerDefine.ReportFileVersion;
|
||||||
report.SchemaType = schema.GetType().FullName;
|
report.SchemaType = schema.GetType().FullName;
|
||||||
report.ScannerGUID = ScannerGUID;
|
report.ScannerGUID = ScannerGUID;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace YooAsset.Editor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件签名
|
/// 文件签名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string FileSign;
|
public string FileSignature;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件版本
|
/// 文件版本
|
||||||
@@ -40,7 +40,7 @@ namespace YooAsset.Editor
|
|||||||
ConfigWrapper setting = JsonUtility.FromJson<ConfigWrapper>(json);
|
ConfigWrapper setting = JsonUtility.FromJson<ConfigWrapper>(json);
|
||||||
|
|
||||||
// 检测配置文件的签名
|
// 检测配置文件的签名
|
||||||
if (setting.FileSign != ScannerDefine.SettingFileSign)
|
if (setting.FileSignature != ScannerDefine.SettingFileSign)
|
||||||
throw new Exception($"导入的配置文件无法识别 : {filePath}");
|
throw new Exception($"导入的配置文件无法识别 : {filePath}");
|
||||||
|
|
||||||
// 检测配置文件的版本
|
// 检测配置文件的版本
|
||||||
@@ -74,7 +74,7 @@ namespace YooAsset.Editor
|
|||||||
File.Delete(savePath);
|
File.Delete(savePath);
|
||||||
|
|
||||||
ConfigWrapper wrapper = new ConfigWrapper();
|
ConfigWrapper wrapper = new ConfigWrapper();
|
||||||
wrapper.FileSign = ScannerDefine.SettingFileSign;
|
wrapper.FileSignature = ScannerDefine.SettingFileSign;
|
||||||
wrapper.FileVersion = ScannerDefine.SettingFileVersion;
|
wrapper.FileVersion = ScannerDefine.SettingFileVersion;
|
||||||
wrapper.Scanners = AssetArtScannerSettingData.Setting.Scanners;
|
wrapper.Scanners = AssetArtScannerSettingData.Setting.Scanners;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace YooAsset.Editor
|
|||||||
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
||||||
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
||||||
var manifestServices = buildParametersContext.Parameters.ManifestDecryptor;
|
var manifestServices = buildParametersContext.Parameters.ManifestDecryptor;
|
||||||
BuiltinFileCatalogTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory);
|
BuiltinCatalogTools.CreateFile(manifestServices, buildPackageName, buildinRootDirectory);
|
||||||
|
|
||||||
// 刷新目录
|
// 刷新目录
|
||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
|
|||||||
@@ -157,12 +157,10 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 内部同步等待方法(子类可选实现)
|
/// 内部释放方法(子类可选实现)
|
||||||
/// 默认抛出异常,如果异步操作需要支持,子类应重写以支持同步等待
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal virtual void InternalWaitForCompletion()
|
internal virtual void InternalDispose()
|
||||||
{
|
{
|
||||||
throw new YooInternalException($"InternalWaitForCompletion() is not implemented: {this.GetType().Name}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -173,6 +171,15 @@ namespace YooAsset
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部同步等待方法(子类可选实现)
|
||||||
|
/// 默认抛出异常,如果异步操作需要支持,子类应重写以支持同步等待
|
||||||
|
/// </summary>
|
||||||
|
internal virtual void InternalWaitForCompletion()
|
||||||
|
{
|
||||||
|
throw new YooInternalException($"InternalWaitForCompletion() is not implemented: {this.GetType().Name}");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加子任务
|
/// 添加子任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -321,27 +328,40 @@ namespace YooAsset
|
|||||||
// 结束记录
|
// 结束记录
|
||||||
DebugEndRecording();
|
DebugEndRecording();
|
||||||
|
|
||||||
if (_onCompleted != null)
|
try
|
||||||
{
|
{
|
||||||
var invocationList = _onCompleted.GetInvocationList();
|
InternalDispose();
|
||||||
foreach (var handler in invocationList)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
try
|
{
|
||||||
{
|
YooLogger.Error($"Exception in {this.GetType().Name}.InternalDispose: {ex}");
|
||||||
((Action<AsyncOperationBase>)handler).Invoke(this);
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
if (_onCompleted != null)
|
||||||
{
|
{
|
||||||
YooLogger.Error($"Exception in completion callback: {ex}");
|
var invocations = _onCompleted.GetInvocationList();
|
||||||
}
|
InvokeSafely(invocations);
|
||||||
}
|
_onCompleted = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCompleted = null;
|
|
||||||
if (_taskCompletionSource != null)
|
if (_taskCompletionSource != null)
|
||||||
_taskCompletionSource.TrySetResult(null);
|
_taskCompletionSource.TrySetResult(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void InvokeSafely(Delegate[] invocations)
|
||||||
|
{
|
||||||
|
foreach (var handler in invocations)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action<AsyncOperationBase>)handler).Invoke(this);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
YooLogger.Error($"Exception in inoke callback: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行一次更新逻辑
|
/// 执行一次更新逻辑
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System;
|
|||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可轮询的下载请求接口
|
/// 下载请求接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IDownloadRequest : IDisposable
|
internal interface IDownloadRequest : IDisposable
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存记录接口
|
/// 缓存条目接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface ICacheEntry
|
internal interface ICacheEntry
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入缓存文件
|
/// 写入缓存文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options);
|
FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清理缓存文件
|
/// 清理缓存文件
|
||||||
@@ -52,12 +52,12 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证缓存文件
|
/// 验证缓存文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options);
|
FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载资源包
|
/// 加载资源包
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options);
|
FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已缓存指定 Bundle
|
/// 是否已缓存指定 Bundle
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载内置资源目录操作
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class LoadBuiltinCatalogOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
TryLoadFileData,
|
||||||
|
RequestFileData,
|
||||||
|
LoadCatalog,
|
||||||
|
CheckResult,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly LoadBuiltinCatalogOptions _options;
|
||||||
|
private IDownloadBytesRequest _downloadBytesRequest;
|
||||||
|
private byte[] _fileData;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载完成的内置资源目录
|
||||||
|
/// </summary>
|
||||||
|
public BuiltinCatalog Catalog;
|
||||||
|
|
||||||
|
internal LoadBuiltinCatalogOperation(LoadBuiltinCatalogOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
internal override void InternalStart()
|
||||||
|
{
|
||||||
|
_steps = ESteps.TryLoadFileData;
|
||||||
|
}
|
||||||
|
internal override void InternalUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.TryLoadFileData)
|
||||||
|
{
|
||||||
|
if (File.Exists(_options.FilePath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_fileData = File.ReadAllBytes(_options.FilePath);
|
||||||
|
_steps = ESteps.LoadCatalog;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Failed to read file: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.RequestFileData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestFileData)
|
||||||
|
{
|
||||||
|
// 注意:从安装包体里解压数据
|
||||||
|
// 注意:从Web服务器下载数据
|
||||||
|
if (_downloadBytesRequest == null)
|
||||||
|
{
|
||||||
|
string url = DownloadSystemTools.ToLocalUrl(_options.FilePath);
|
||||||
|
var args = new DownloadDataRequestArgs(url, 60, 0);
|
||||||
|
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
|
||||||
|
_downloadBytesRequest.SendRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_downloadBytesRequest.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
|
||||||
|
{
|
||||||
|
_fileData = _downloadBytesRequest.Result;
|
||||||
|
_steps = ESteps.LoadCatalog;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _downloadBytesRequest.Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadCatalog)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Catalog = BuiltinCatalogTools.DeserializeFromBinary(_fileData);
|
||||||
|
_steps = ESteps.CheckResult;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Failed to load catalog: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.CheckResult)
|
||||||
|
{
|
||||||
|
if (Catalog.PackageName == _options.PackageName)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Catalog package name {Catalog.PackageName} cannot match the file cache package name {_options.PackageName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_downloadBytesRequest != null)
|
||||||
|
{
|
||||||
|
_downloadBytesRequest.Dispose();
|
||||||
|
_downloadBytesRequest = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载内置资源目录操作选项
|
||||||
|
/// </summary>
|
||||||
|
internal struct LoadBuiltinCatalogOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹名称
|
||||||
|
/// </summary>
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载后台
|
||||||
|
/// </summary>
|
||||||
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 236fcfdca8d96624087432269508ccee
|
guid: 23227e3feab43ab4693cc17ad519f364
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从本地文件加载 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class LoadLocalAssetBundleOperation : FCLoadBundleOperation
|
internal class LoadLocalAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -13,14 +16,16 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly PackageBundle _bundle;
|
|
||||||
private readonly LoadLocalAssetBundleOptions _options;
|
private readonly LoadLocalAssetBundleOptions _options;
|
||||||
private AssetBundleCreateRequest _createRequest;
|
private AssetBundleCreateRequest _createRequest;
|
||||||
private AssetBundle _assetBundle;
|
private AssetBundle _assetBundle;
|
||||||
private Stream _loadStream;
|
private Stream _loadStream;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public bool UnityEngineLoadFailed = false;
|
/// <summary>
|
||||||
|
/// Unity引擎加载是否失败
|
||||||
|
/// </summary>
|
||||||
|
public bool UnityEngineLoadFailed { get; private set; } = false;
|
||||||
|
|
||||||
public LoadLocalAssetBundleOperation(LoadLocalAssetBundleOptions options)
|
public LoadLocalAssetBundleOperation(LoadLocalAssetBundleOptions options)
|
||||||
{
|
{
|
||||||
@@ -37,13 +42,13 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.LoadBundle)
|
if (_steps == ESteps.LoadBundle)
|
||||||
{
|
{
|
||||||
if (_bundle.IsEncrypted == false)
|
if (_options.Bundle.IsEncrypted == false)
|
||||||
{
|
{
|
||||||
LoadFromFile();
|
LoadFromFile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var decryptor = _options.Decryptor;
|
var decryptor = _options.AssetBundleDecryptor;
|
||||||
if (decryptor == null)
|
if (decryptor == null)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
@@ -52,17 +57,18 @@ namespace YooAsset
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadResult result;
|
||||||
if (decryptor is IBundleOffsetDecryptor offsetDecryptor)
|
if (decryptor is IBundleOffsetDecryptor offsetDecryptor)
|
||||||
{
|
{
|
||||||
LoadFromFileWithOffset(offsetDecryptor);
|
result = LoadFromFileWithOffset(offsetDecryptor);
|
||||||
}
|
}
|
||||||
else if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
else if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
||||||
{
|
{
|
||||||
LoadFromMemory(memoryDecryptor);
|
result = LoadFromMemory(memoryDecryptor);
|
||||||
}
|
}
|
||||||
else if (decryptor is IBundleStreamDecryptor streamDecryptor)
|
else if (decryptor is IBundleStreamDecryptor streamDecryptor)
|
||||||
{
|
{
|
||||||
LoadFromStream(streamDecryptor);
|
result = LoadFromStream(streamDecryptor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -71,6 +77,14 @@ namespace YooAsset
|
|||||||
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
|
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.Succeeded == false)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = result.Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckResult;
|
||||||
@@ -82,8 +96,8 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
{
|
{
|
||||||
// 强制挂起主线程(注意:该操作会很耗时)
|
// 强制挂起主线程(注意:该操作会很耗时)
|
||||||
YooLogger.Warning("Suspend the main thread to load unity bundle.");
|
YooLogger.Warning("Suspending the main thread to load Unity bundle.");
|
||||||
_assetBundle = _createRequest.assetBundle;
|
_assetBundle = _createRequest.assetBundle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -100,6 +114,7 @@ namespace YooAsset
|
|||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "Unity engine load failed.";
|
Error = "Unity engine load failed.";
|
||||||
UnityEngineLoadFailed = true;
|
UnityEngineLoadFailed = true;
|
||||||
|
CleanupStream();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -121,10 +136,10 @@ namespace YooAsset
|
|||||||
else
|
else
|
||||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath);
|
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath);
|
||||||
}
|
}
|
||||||
private void LoadFromFileWithOffset(IBundleOffsetDecryptor decryptor)
|
private LoadResult LoadFromFileWithOffset(IBundleOffsetDecryptor decryptor)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _bundle;
|
args.Bundle = _options.Bundle;
|
||||||
args.FilePath = _options.FilePath;
|
args.FilePath = _options.FilePath;
|
||||||
uint offset = decryptor.GetFileOffset(args);
|
uint offset = decryptor.GetFileOffset(args);
|
||||||
|
|
||||||
@@ -132,31 +147,51 @@ namespace YooAsset
|
|||||||
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, offset);
|
_assetBundle = AssetBundle.LoadFromFile(_options.FilePath, 0, offset);
|
||||||
else
|
else
|
||||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath, 0, offset);
|
_createRequest = AssetBundle.LoadFromFileAsync(_options.FilePath, 0, offset);
|
||||||
|
|
||||||
|
return LoadResult.Default();
|
||||||
}
|
}
|
||||||
private void LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _bundle;
|
args.Bundle = _options.Bundle;
|
||||||
args.FilePath = _options.FilePath;
|
args.FilePath = _options.FilePath;
|
||||||
var binaryData = decryptor.GetDecryptData(args);
|
var binaryData = decryptor.GetDecryptData(args);
|
||||||
|
if (binaryData == null)
|
||||||
|
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||||
|
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
_assetBundle = AssetBundle.LoadFromMemory(binaryData);
|
_assetBundle = AssetBundle.LoadFromMemory(binaryData);
|
||||||
else
|
else
|
||||||
_createRequest = AssetBundle.LoadFromMemoryAsync(binaryData);
|
_createRequest = AssetBundle.LoadFromMemoryAsync(binaryData);
|
||||||
|
|
||||||
|
return LoadResult.Default();
|
||||||
}
|
}
|
||||||
private void LoadFromStream(IBundleStreamDecryptor decryptor)
|
private LoadResult LoadFromStream(IBundleStreamDecryptor decryptor)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _bundle;
|
args.Bundle = _options.Bundle;
|
||||||
args.FilePath = _options.FilePath;
|
args.FilePath = _options.FilePath;
|
||||||
uint bufferSize = decryptor.GetReadBufferSize(args);
|
uint bufferSize = decryptor.GetReadBufferSize(args);
|
||||||
_loadStream = decryptor.GetDecryptStream(args);
|
_loadStream = decryptor.GetDecryptStream(args);
|
||||||
|
if (_loadStream == null)
|
||||||
|
return LoadResult.Failure($"{_options.CacheName} decryptor returned null stream.");
|
||||||
|
|
||||||
|
uint unityCRC = 0;
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
_assetBundle = AssetBundle.LoadFromStream(_loadStream, 0, bufferSize);
|
_assetBundle = AssetBundle.LoadFromStream(_loadStream, unityCRC, bufferSize);
|
||||||
else
|
else
|
||||||
_createRequest = AssetBundle.LoadFromStreamAsync(_loadStream, 0, bufferSize);
|
_createRequest = AssetBundle.LoadFromStreamAsync(_loadStream, unityCRC, bufferSize);
|
||||||
|
|
||||||
|
return LoadResult.Default();
|
||||||
|
}
|
||||||
|
private void CleanupStream()
|
||||||
|
{
|
||||||
|
if (_loadStream != null)
|
||||||
|
{
|
||||||
|
_loadStream.Close();
|
||||||
|
_loadStream.Dispose();
|
||||||
|
_loadStream = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,9 +22,9 @@ namespace YooAsset
|
|||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解密接口
|
/// AssetBundle 解密器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBundleDecryptor Decryptor { get; set; }
|
public IBundleDecryptor AssetBundleDecryptor { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,6 +3,9 @@ using System.IO;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从本地加载 RawBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class LoadLocalRawBundleOperation : FCLoadBundleOperation
|
internal class LoadLocalRawBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -34,7 +37,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
if (_options.Bundle.IsEncrypted == false)
|
if (_options.Bundle.IsEncrypted == false)
|
||||||
{
|
{
|
||||||
if (IsSupportFileIO(_options.FilePath) == false)
|
if (SupportsFileIO(_options.FilePath) == false)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
@@ -46,7 +49,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var decryptor = _options.Decryptor;
|
var decryptor = _options.RawBundleDecryptor;
|
||||||
if (decryptor == null)
|
if (decryptor == null)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
@@ -55,9 +58,10 @@ namespace YooAsset
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadResult result;
|
||||||
if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
if (decryptor is IBundleMemoryDecryptor memoryDecryptor)
|
||||||
{
|
{
|
||||||
LoadFromMemory(memoryDecryptor);
|
result = LoadFromMemory(memoryDecryptor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -66,6 +70,14 @@ namespace YooAsset
|
|||||||
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
|
Error = $"{_options.CacheName} not support {decryptor.GetType().Name}";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.Succeeded == false)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = result.Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckResult;
|
||||||
@@ -95,17 +107,19 @@ namespace YooAsset
|
|||||||
private void LoadFromFile()
|
private void LoadFromFile()
|
||||||
{
|
{
|
||||||
byte[] data = File.ReadAllBytes(_options.FilePath);
|
byte[] data = File.ReadAllBytes(_options.FilePath);
|
||||||
if (data != null)
|
_rawBundle = new RawBundle(data);
|
||||||
_rawBundle = new RawBundle(data);
|
|
||||||
}
|
}
|
||||||
private void LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _options.Bundle;
|
args.Bundle = _options.Bundle;
|
||||||
args.FilePath = _options.FilePath;
|
args.FilePath = _options.FilePath;
|
||||||
var binaryData = decryptor.GetDecryptData(args);
|
var binaryData = decryptor.GetDecryptData(args);
|
||||||
if (binaryData != null)
|
if (binaryData == null)
|
||||||
_rawBundle = new RawBundle(binaryData);
|
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||||
|
|
||||||
|
_rawBundle = new RawBundle(binaryData);
|
||||||
|
return LoadResult.Default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,8 @@ namespace YooAsset
|
|||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解密接口
|
/// RawBundle 解密器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBundleDecryptor Decryptor { get; set; }
|
public IBundleDecryptor RawBundleDecryptor { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,24 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从网络加载 AssetBundle 操作的抽象基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class LoadWebAssetBundleOperation : FCLoadBundleOperation
|
internal abstract class LoadWebAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从网络加载未加密 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class LoadWebNormalAssetBundleOperation : LoadWebAssetBundleOperation
|
internal class LoadWebNormalAssetBundleOperation : LoadWebAssetBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
DownloadBundle,
|
BundleRequest,
|
||||||
CheckResult,
|
CheckRequest,
|
||||||
TryAgain,
|
TryAgain,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
@@ -21,7 +27,7 @@ namespace YooAsset
|
|||||||
private IDownloadAssetBundleRequest _downloadAssetBundleRequest;
|
private IDownloadAssetBundleRequest _downloadAssetBundleRequest;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
// 失败重试
|
// 失败重试
|
||||||
private int _requestCount = 0;
|
private int _requestCount = 0;
|
||||||
private float _tryAgainTimer = 0;
|
private float _tryAgainTimer = 0;
|
||||||
private int _failedTryAgain;
|
private int _failedTryAgain;
|
||||||
@@ -29,27 +35,27 @@ namespace YooAsset
|
|||||||
public LoadWebNormalAssetBundleOperation(LoadWebAssetBundleOptions options)
|
public LoadWebNormalAssetBundleOperation(LoadWebAssetBundleOptions options)
|
||||||
{
|
{
|
||||||
_options = options;
|
_options = options;
|
||||||
_failedTryAgain = int.MaxValue; //注意:网络原因失败后,重新尝试直到成功
|
_failedTryAgain = int.MaxValue; //注意:网络原因失败后,重新尝试直到成功
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.DownloadBundle;
|
_steps = ESteps.BundleRequest;
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.DownloadBundle)
|
if (_steps == ESteps.BundleRequest)
|
||||||
{
|
{
|
||||||
string url = GetRequestURL();
|
string url = GetRequestURL();
|
||||||
var args = new DownloadAssetBundleRequestArgs(url, 0, _options.WatchdogTimeout, _options.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
|
var args = new DownloadAssetBundleRequestArgs(url, 0, _options.WatchdogTimeout, _options.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
|
||||||
_downloadAssetBundleRequest = _options.DownloadBackend.CreateAssetBundleRequest(args);
|
_downloadAssetBundleRequest = _options.DownloadBackend.CreateAssetBundleRequest(args);
|
||||||
_downloadAssetBundleRequest.SendRequest();
|
_downloadAssetBundleRequest.SendRequest();
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResult)
|
if (_steps == ESteps.CheckRequest)
|
||||||
{
|
{
|
||||||
Progress = _downloadAssetBundleRequest.DownloadProgress;
|
Progress = _downloadAssetBundleRequest.DownloadProgress;
|
||||||
if (_downloadAssetBundleRequest.IsDone == false)
|
if (_downloadAssetBundleRequest.IsDone == false)
|
||||||
@@ -62,7 +68,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Fatal error: dwonload asset bundle is null.";
|
Error = $"Fatal error: downloaded asset bundle is null.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -73,7 +79,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_failedTryAgain > 0)
|
if (_failedTryAgain > 0 && IsRetryableError(_downloadAssetBundleRequest.HttpCode))
|
||||||
{
|
{
|
||||||
_steps = ESteps.TryAgain;
|
_steps = ESteps.TryAgain;
|
||||||
}
|
}
|
||||||
@@ -84,27 +90,39 @@ namespace YooAsset
|
|||||||
Error = _downloadAssetBundleRequest.Error;
|
Error = _downloadAssetBundleRequest.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最终释放请求器
|
|
||||||
_downloadAssetBundleRequest.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.TryAgain)
|
if (_steps == ESteps.TryAgain)
|
||||||
{
|
{
|
||||||
|
// 注意:失败后释放网络请求
|
||||||
|
if (_downloadAssetBundleRequest != null)
|
||||||
|
{
|
||||||
|
_downloadAssetBundleRequest.Dispose();
|
||||||
|
_downloadAssetBundleRequest = null;
|
||||||
|
}
|
||||||
|
|
||||||
_tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
|
_tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
|
||||||
if (_tryAgainTimer > 1f)
|
if (_tryAgainTimer > 1f)
|
||||||
{
|
{
|
||||||
_tryAgainTimer = 0f;
|
_tryAgainTimer = 0f;
|
||||||
_failedTryAgain--;
|
_failedTryAgain--;
|
||||||
Progress = 0f;
|
Progress = 0f;
|
||||||
_steps = ESteps.DownloadBundle;
|
_steps = ESteps.BundleRequest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal override void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_downloadAssetBundleRequest != null)
|
||||||
|
{
|
||||||
|
_downloadAssetBundleRequest.Dispose();
|
||||||
|
_downloadAssetBundleRequest = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetRequestURL()
|
private string GetRequestURL()
|
||||||
{
|
{
|
||||||
// 轮流返回请求地址
|
// 轮流返回请求地址
|
||||||
_requestCount++;
|
_requestCount++;
|
||||||
if (_requestCount % 2 == 0)
|
if (_requestCount % 2 == 0)
|
||||||
return _options.FallbackURL;
|
return _options.FallbackURL;
|
||||||
@@ -113,12 +131,18 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从网络加载加密的 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class LoadWebEncryptedAssetBundleOperation : LoadWebAssetBundleOperation
|
internal class LoadWebEncryptedAssetBundleOperation : LoadWebAssetBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
DownloadData,
|
DataRequest,
|
||||||
|
CheckRequest,
|
||||||
|
VerifyData,
|
||||||
|
LoadBundle,
|
||||||
CheckResult,
|
CheckResult,
|
||||||
TryAgain,
|
TryAgain,
|
||||||
Done,
|
Done,
|
||||||
@@ -127,9 +151,10 @@ namespace YooAsset
|
|||||||
protected readonly LoadWebAssetBundleOptions _options;
|
protected readonly LoadWebAssetBundleOptions _options;
|
||||||
private IDownloadBytesRequest _downloadBytesRequest;
|
private IDownloadBytesRequest _downloadBytesRequest;
|
||||||
private IBundleMemoryDecryptor _decryptor;
|
private IBundleMemoryDecryptor _decryptor;
|
||||||
|
private AssetBundleCreateRequest _createRequest;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
// 失败重试
|
// 失败重试
|
||||||
private int _requestCount = 0;
|
private int _requestCount = 0;
|
||||||
private float _tryAgainTimer = 0;
|
private float _tryAgainTimer = 0;
|
||||||
private int _failedTryAgain;
|
private int _failedTryAgain;
|
||||||
@@ -137,20 +162,20 @@ namespace YooAsset
|
|||||||
public LoadWebEncryptedAssetBundleOperation(LoadWebAssetBundleOptions options)
|
public LoadWebEncryptedAssetBundleOperation(LoadWebAssetBundleOptions options)
|
||||||
{
|
{
|
||||||
_options = options;
|
_options = options;
|
||||||
_failedTryAgain = int.MaxValue; //注意:网络原因失败后,重新尝试直到成功
|
_failedTryAgain = int.MaxValue; //注意:网络原因失败后,重新尝试直到成功
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.DownloadData;
|
_steps = ESteps.DataRequest;
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.DownloadData)
|
if (_steps == ESteps.DataRequest)
|
||||||
{
|
{
|
||||||
var decryptor = _options.Decryptor;
|
var decryptor = _options.AssetBundleDecryptor;
|
||||||
if (decryptor == null)
|
if (decryptor == null)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
@@ -161,12 +186,12 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (decryptor is IBundleMemoryDecryptor)
|
if (decryptor is IBundleMemoryDecryptor)
|
||||||
{
|
{
|
||||||
string url = GetRequestURL();
|
|
||||||
_decryptor = decryptor as IBundleMemoryDecryptor;
|
_decryptor = decryptor as IBundleMemoryDecryptor;
|
||||||
|
string url = GetRequestURL();
|
||||||
var args = new DownloadDataRequestArgs(url, 0, _options.WatchdogTimeout);
|
var args = new DownloadDataRequestArgs(url, 0, _options.WatchdogTimeout);
|
||||||
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
|
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
|
||||||
_downloadBytesRequest.SendRequest();
|
_downloadBytesRequest.SendRequest();
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.CheckRequest;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -177,32 +202,19 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResult)
|
if (_steps == ESteps.CheckRequest)
|
||||||
{
|
{
|
||||||
Progress = _downloadBytesRequest.DownloadProgress;
|
Progress = _downloadBytesRequest.DownloadProgress;
|
||||||
if (_downloadBytesRequest.IsDone == false)
|
if (_downloadBytesRequest.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 检查网络错误
|
|
||||||
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
|
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
|
||||||
{
|
{
|
||||||
var assetBundle = LoadFromMemory(_decryptor, _downloadBytesRequest.Result);
|
_steps = ESteps.VerifyData;
|
||||||
if (assetBundle == null)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = "Unity engine load failed.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
BundleResult = new AssetBundleResult(_downloadBytesRequest.Url, _options.Bundle, assetBundle, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_failedTryAgain > 0)
|
if (_failedTryAgain > 0 && IsRetryableError(_downloadBytesRequest.HttpCode))
|
||||||
{
|
{
|
||||||
_steps = ESteps.TryAgain;
|
_steps = ESteps.TryAgain;
|
||||||
}
|
}
|
||||||
@@ -213,35 +225,118 @@ namespace YooAsset
|
|||||||
Error = _downloadBytesRequest.Error;
|
Error = _downloadBytesRequest.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 最终释放请求器
|
if (_steps == ESteps.VerifyData)
|
||||||
_downloadBytesRequest.Dispose();
|
{
|
||||||
|
// 注意:网络/代理/服务器异常导致内容不完整但请求仍成功
|
||||||
|
EFileVerifyResult verifyResult;
|
||||||
|
if (_options.DownloadVerifyLevel == EFileVerifyLevel.Low || _options.DownloadVerifyLevel == EFileVerifyLevel.Middle)
|
||||||
|
verifyResult = FileVerifyTools.FileVerify(_downloadBytesRequest.Result, _options.Bundle.FileSize, 0);
|
||||||
|
else if (_options.DownloadVerifyLevel == EFileVerifyLevel.High)
|
||||||
|
verifyResult = FileVerifyTools.FileVerify(_downloadBytesRequest.Result, _options.Bundle.FileSize, _options.Bundle.FileCRC);
|
||||||
|
else
|
||||||
|
throw new System.NotImplementedException(_options.DownloadVerifyLevel.ToString());
|
||||||
|
|
||||||
|
if (verifyResult == EFileVerifyResult.Succeed)
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadBundle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string error = $"[WebBundleVerify] Verify failed. Url:{_downloadBytesRequest.Url} Level: {_options.DownloadVerifyLevel} Result: {verifyResult}";
|
||||||
|
YooLogger.Warning(error);
|
||||||
|
|
||||||
|
if (_failedTryAgain > 0)
|
||||||
|
{
|
||||||
|
_steps = ESteps.TryAgain;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadBundle)
|
||||||
|
{
|
||||||
|
LoadResult result = LoadFromMemory(_decryptor, _downloadBytesRequest.Result);
|
||||||
|
if (result.Succeeded == false)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = result.Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.CheckResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.CheckResult)
|
||||||
|
{
|
||||||
|
if (_createRequest.isDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var assetBundle = _createRequest.assetBundle;
|
||||||
|
if (assetBundle == null)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = "Unity engine load failed.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
|
BundleResult = new AssetBundleResult(_downloadBytesRequest.Url, _options.Bundle, assetBundle, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.TryAgain)
|
if (_steps == ESteps.TryAgain)
|
||||||
{
|
{
|
||||||
|
// 注意:失败后释放网络请求
|
||||||
|
if (_downloadBytesRequest != null)
|
||||||
|
{
|
||||||
|
_downloadBytesRequest.Dispose();
|
||||||
|
_downloadBytesRequest = null;
|
||||||
|
}
|
||||||
|
|
||||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||||
if (_tryAgainTimer > 1f)
|
if (_tryAgainTimer > 1f)
|
||||||
{
|
{
|
||||||
_tryAgainTimer = 0f;
|
_tryAgainTimer = 0f;
|
||||||
_failedTryAgain--;
|
_failedTryAgain--;
|
||||||
Progress = 0f;
|
Progress = 0f;
|
||||||
_steps = ESteps.DownloadData;
|
_steps = ESteps.DataRequest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal override void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_downloadBytesRequest != null)
|
||||||
|
{
|
||||||
|
_downloadBytesRequest.Dispose();
|
||||||
|
_downloadBytesRequest = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private AssetBundle LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData)
|
private LoadResult LoadFromMemory(IBundleMemoryDecryptor decryptor, byte[] fileData)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _options.Bundle;
|
args.Bundle = _options.Bundle;
|
||||||
args.FileData = fileData;
|
args.FileData = fileData;
|
||||||
var binaryData = decryptor.GetDecryptData(args);
|
var binaryData = decryptor.GetDecryptData(args);
|
||||||
return AssetBundle.LoadFromMemory(binaryData);
|
if (binaryData == null)
|
||||||
|
return LoadResult.Failure($"{_options.CacheName} decryptor returned null data.");
|
||||||
|
|
||||||
|
_createRequest = AssetBundle.LoadFromMemoryAsync(binaryData);
|
||||||
|
return LoadResult.Default();
|
||||||
}
|
}
|
||||||
private string GetRequestURL()
|
private string GetRequestURL()
|
||||||
{
|
{
|
||||||
// 轮流返回请求地址
|
// 轮流返回请求地址
|
||||||
_requestCount++;
|
_requestCount++;
|
||||||
if (_requestCount % 2 == 0)
|
if (_requestCount % 2 == 0)
|
||||||
return _options.FallbackURL;
|
return _options.FallbackURL;
|
||||||
@@ -22,20 +22,25 @@ namespace YooAsset
|
|||||||
public string MainURL { get; set; }
|
public string MainURL { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求地址
|
/// 备用请求地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string FallbackURL { get; set; }
|
public string FallbackURL { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解密接口
|
/// AssetBundle 解密器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBundleDecryptor Decryptor { get; set; }
|
public IBundleDecryptor AssetBundleDecryptor { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载后台接口
|
/// 下载后台接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDownloadBackend DownloadBackend { get; set; }
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载数据校验级别
|
||||||
|
/// </summary>
|
||||||
|
public EFileVerifyLevel DownloadVerifyLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 看门狗超时时间
|
/// 看门狗超时时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 清理缓存操作基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class FCClearCacheOperation : AsyncOperationBase
|
internal abstract class FCClearCacheOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理缓存完成操作
|
||||||
|
/// </summary>
|
||||||
internal class FCClearCacheCompleteOperation : FCClearCacheOperation
|
internal class FCClearCacheCompleteOperation : FCClearCacheOperation
|
||||||
{
|
{
|
||||||
private readonly string _error;
|
private readonly string _error;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件缓存初始化操作基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class FCInitializeOperation : AsyncOperationBase
|
internal abstract class FCInitializeOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,91 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载资源包操作基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class FCLoadBundleOperation : AsyncOperationBase
|
internal abstract class FCLoadBundleOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
|
protected struct LoadResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 错误信息
|
||||||
|
/// </summary>
|
||||||
|
public readonly string Error;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载成功
|
||||||
|
/// </summary>
|
||||||
|
public bool Succeeded
|
||||||
|
{
|
||||||
|
get { return Error == null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadResult(string error)
|
||||||
|
{
|
||||||
|
Error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoadResult Default()
|
||||||
|
{
|
||||||
|
return new LoadResult(null);
|
||||||
|
}
|
||||||
|
public static LoadResult Failure(string error)
|
||||||
|
{
|
||||||
|
return new LoadResult(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包加载结果
|
||||||
|
/// </summary>
|
||||||
public IBundleResult BundleResult { get; protected set; }
|
public IBundleResult BundleResult { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查文件路径是否支持 FileIO 读取
|
/// 检查文件路径是否支持 FileIO 读取
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected bool IsSupportFileIO(string filePath)
|
protected bool SupportsFileIO(string filePath)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(filePath))
|
if (string.IsNullOrEmpty(filePath))
|
||||||
return true;
|
return false;
|
||||||
if (filePath.StartsWith("jar:") || filePath.StartsWith("content:"))
|
if (filePath.StartsWith("jar:") || filePath.StartsWith("content:"))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否为可重试的错误
|
||||||
|
/// </summary>
|
||||||
|
protected bool IsRetryableError(long httpCode)
|
||||||
|
{
|
||||||
|
// HTTP 状态码
|
||||||
|
// 1xx 信息响应
|
||||||
|
// 2xx 成功响应
|
||||||
|
// 3xx 重定向消息
|
||||||
|
// 4xx 客户端错误响应
|
||||||
|
// 5xx 服务器错误响应
|
||||||
|
|
||||||
|
if (httpCode == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 4xx 客户端错误不可重试
|
||||||
|
// 说明:408 Request Timeout
|
||||||
|
// 说明:429 Too Many Requests
|
||||||
|
if (httpCode >= 400 && httpCode < 500)
|
||||||
|
return httpCode == 408 || httpCode == 429;
|
||||||
|
|
||||||
|
// 其它情况可重试
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载资源包失败操作
|
||||||
|
/// </summary>
|
||||||
internal sealed class FCLoadBundleErrorOperation : FCLoadBundleOperation
|
internal sealed class FCLoadBundleErrorOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private readonly string _error;
|
private readonly string _error;
|
||||||
|
|
||||||
internal FCLoadBundleErrorOperation(string error)
|
internal FCLoadBundleErrorOperation(string error)
|
||||||
{
|
{
|
||||||
_error = error;
|
_error = error;
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal struct LoadBundleOptions
|
/// <summary>
|
||||||
|
/// 加载资源包操作选项
|
||||||
|
/// </summary>
|
||||||
|
internal readonly struct FCLoadBundleOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 资源包
|
/// 资源包
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly PackageBundle Bundle;
|
public readonly PackageBundle Bundle;
|
||||||
|
|
||||||
public LoadBundleOptions(PackageBundle bundle)
|
public FCLoadBundleOptions(PackageBundle bundle)
|
||||||
{
|
{
|
||||||
Bundle = bundle;
|
Bundle = bundle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 验证缓存操作基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class FCVerifyCacheOperation : AsyncOperationBase
|
internal abstract class FCVerifyCacheOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证缓存完成操作
|
||||||
|
/// </summary>
|
||||||
internal class FCVerifyCacheCompleteOperation : FCVerifyCacheOperation
|
internal class FCVerifyCacheCompleteOperation : FCVerifyCacheOperation
|
||||||
{
|
{
|
||||||
private readonly string _error;
|
private readonly string _error;
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal struct VerifyCacheOptions
|
/// <summary>
|
||||||
|
/// 验证缓存操作选项
|
||||||
|
/// </summary>
|
||||||
|
internal struct FCVerifyCacheOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 要验证的资源包
|
/// 要验证的资源包
|
||||||
@@ -9,8 +12,8 @@ namespace YooAsset
|
|||||||
public PackageBundle Bundle { get; set; }
|
public PackageBundle Bundle { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 失败后直接移除缓存
|
/// 失败后直接移除缓存条目
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool FailedDeleteCache { get; set; }
|
public bool DeleteCacheEntryOnFailure { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 写入缓存操作基类
|
||||||
|
/// </summary>
|
||||||
internal abstract class FCWriteCacheOperation : AsyncOperationBase
|
internal abstract class FCWriteCacheOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入缓存完成操作
|
||||||
|
/// </summary>
|
||||||
internal class FCWriteCacheCompleteOperation : FCWriteCacheOperation
|
internal class FCWriteCacheCompleteOperation : FCWriteCacheOperation
|
||||||
{
|
{
|
||||||
private readonly string _error;
|
private readonly string _error;
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal struct WriteCacheOptions
|
/// <summary>
|
||||||
|
/// 写入缓存操作选项
|
||||||
|
/// </summary>
|
||||||
|
internal struct FCWriteCacheOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 要缓存的资源包
|
/// 要缓存的资源包
|
||||||
|
|||||||
@@ -1,19 +1,29 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 内置资源清单目录
|
/// 内置资源目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
internal class BuiltinFileCatalog
|
internal class BuiltinCatalog
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置资源文件条目
|
||||||
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class FileWrapper
|
public class FileEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
public string BundleGUID;
|
public string BundleGUID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包文件名
|
||||||
|
/// </summary>
|
||||||
public string FileName;
|
public string FileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,8 +43,8 @@ namespace YooAsset
|
|||||||
public string PackageVersion;
|
public string PackageVersion;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件列表
|
/// 文件条目列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<FileWrapper> Wrappers = new List<FileWrapper>();
|
public List<FileEntry> FileEntries = new List<FileEntry>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal class BuiltinFileCatalogDefine
|
/// <summary>
|
||||||
|
/// 内置资源目录常量定义
|
||||||
|
/// </summary>
|
||||||
|
internal class BuiltinCatalogDefine
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件极限大小(100MB)
|
/// 文件极限大小(100MB)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int FileMaxSize = 104857600;
|
public const int MaxFileSize = 104857600;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件头标记
|
/// 文件头标记
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint FileSign = 0x133C5EE;
|
public const uint FileHeader = 0x133C5EE;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件格式版本
|
/// 文件格式版本
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal static class BuiltinFileCatalogTools
|
/// <summary>
|
||||||
|
/// 内置资源目录工具类
|
||||||
|
/// </summary>
|
||||||
|
internal static class BuiltinCatalogTools
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -21,7 +24,7 @@ namespace YooAsset
|
|||||||
string versionFilePath = $"{packageDirectory}/{versionFileName}";
|
string versionFilePath = $"{packageDirectory}/{versionFileName}";
|
||||||
if (File.Exists(versionFilePath) == false)
|
if (File.Exists(versionFilePath) == false)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Can not found package version file : {versionFilePath}");
|
Debug.LogError($"Package version file not found: {versionFilePath}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +38,7 @@ namespace YooAsset
|
|||||||
string manifestFilePath = $"{packageDirectory}/{manifestFileName}";
|
string manifestFilePath = $"{packageDirectory}/{manifestFileName}";
|
||||||
if (File.Exists(manifestFilePath) == false)
|
if (File.Exists(manifestFilePath) == false)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Can not found package manifest file : {manifestFilePath}");
|
Debug.LogError($"Package manifest file not found: {manifestFilePath}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,29 +56,29 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建内置清单实例
|
// 创建内置清单实例
|
||||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
var buildinCatalog = new BuiltinCatalog();
|
||||||
buildinFileCatalog.FileVersion = BuiltinFileCatalogDefine.FileVersion;
|
buildinCatalog.FileVersion = BuiltinCatalogDefine.FileVersion;
|
||||||
buildinFileCatalog.PackageName = packageName;
|
buildinCatalog.PackageName = packageName;
|
||||||
buildinFileCatalog.PackageVersion = packageVersion;
|
buildinCatalog.PackageVersion = packageVersion;
|
||||||
|
|
||||||
// 创建白名单查询集合
|
// 创建白名单查询集合
|
||||||
HashSet<string> whiteFileList = new HashSet<string>
|
HashSet<string> whiteFileNameList = new HashSet<string>
|
||||||
{
|
{
|
||||||
"link.xml",
|
"link.xml",
|
||||||
"buildlogtep.json",
|
"buildlogtep.json",
|
||||||
BuiltinFileCatalogDefine.JsonFileName,
|
BuiltinCatalogDefine.JsonFileName,
|
||||||
BuiltinFileCatalogDefine.BinaryFileName
|
BuiltinCatalogDefine.BinaryFileName
|
||||||
};
|
};
|
||||||
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
string packageVersionFileName = YooAssetSettingsData.GetPackageVersionFileName(packageName);
|
||||||
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
|
string packageHashFileName = YooAssetSettingsData.GetPackageHashFileName(packageName, packageVersion);
|
||||||
string manifestBinaryFIleName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
string manifestBinaryFileName = YooAssetSettingsData.GetManifestBinaryFileName(packageName, packageVersion);
|
||||||
string manifestJsonFIleName = YooAssetSettingsData.GetManifestJsonFileName(packageName, packageVersion);
|
string manifestJsonFileName = YooAssetSettingsData.GetManifestJsonFileName(packageName, packageVersion);
|
||||||
string reportFileName = YooAssetSettingsData.GetBuildReportFileName(packageName, packageVersion);
|
string reportFileName = YooAssetSettingsData.GetBuildReportFileName(packageName, packageVersion);
|
||||||
whiteFileList.Add(packageVersionFileName);
|
whiteFileNameList.Add(packageVersionFileName);
|
||||||
whiteFileList.Add(packageHashFileName);
|
whiteFileNameList.Add(packageHashFileName);
|
||||||
whiteFileList.Add(manifestBinaryFIleName);
|
whiteFileNameList.Add(manifestBinaryFileName);
|
||||||
whiteFileList.Add(manifestJsonFIleName);
|
whiteFileNameList.Add(manifestJsonFileName);
|
||||||
whiteFileList.Add(reportFileName);
|
whiteFileNameList.Add(reportFileName);
|
||||||
|
|
||||||
// 记录所有内置资源文件
|
// 记录所有内置资源文件
|
||||||
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);
|
DirectoryInfo rootDirectory = new DirectoryInfo(packageDirectory);
|
||||||
@@ -85,37 +88,37 @@ namespace YooAsset
|
|||||||
if (fileInfo.Extension == ".meta")
|
if (fileInfo.Extension == ".meta")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (whiteFileList.Contains(fileInfo.Name))
|
if (whiteFileNameList.Contains(fileInfo.Name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string fileName = fileInfo.Name;
|
string fileName = fileInfo.Name;
|
||||||
if (fileMapping.TryGetValue(fileName, out string bundleGUID))
|
if (fileMapping.TryGetValue(fileName, out string bundleGUID))
|
||||||
{
|
{
|
||||||
var wrapper = new BuiltinFileCatalog.FileWrapper();
|
var fileEntry = new BuiltinCatalog.FileEntry();
|
||||||
wrapper.BundleGUID = bundleGUID;
|
fileEntry.BundleGUID = bundleGUID;
|
||||||
wrapper.FileName = fileName;
|
fileEntry.FileName = fileName;
|
||||||
buildinFileCatalog.Wrappers.Add(wrapper);
|
buildinCatalog.FileEntries.Add(fileEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Failed mapping file : {fileName}");
|
Debug.LogWarning($"Failed to map file: {fileName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建输出文件
|
// 创建输出文件
|
||||||
string jsonFilePath = $"{packageDirectory}/{BuiltinFileCatalogDefine.JsonFileName}";
|
string jsonFilePath = $"{packageDirectory}/{BuiltinCatalogDefine.JsonFileName}";
|
||||||
if (File.Exists(jsonFilePath))
|
if (File.Exists(jsonFilePath))
|
||||||
File.Delete(jsonFilePath);
|
File.Delete(jsonFilePath);
|
||||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
SerializeToJson(jsonFilePath, buildinCatalog);
|
||||||
|
|
||||||
// 创建输出文件
|
// 创建输出文件
|
||||||
string binaryFilePath = $"{packageDirectory}/{BuiltinFileCatalogDefine.BinaryFileName}";
|
string binaryFilePath = $"{packageDirectory}/{BuiltinCatalogDefine.BinaryFileName}";
|
||||||
if (File.Exists(binaryFilePath))
|
if (File.Exists(binaryFilePath))
|
||||||
File.Delete(binaryFilePath);
|
File.Delete(binaryFilePath);
|
||||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
SerializeToBinary(binaryFilePath, buildinCatalog);
|
||||||
|
|
||||||
UnityEditor.AssetDatabase.Refresh();
|
UnityEditor.AssetDatabase.Refresh();
|
||||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
Debug.Log($"Successfully saved catalog file: {binaryFilePath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,71 +128,62 @@ namespace YooAsset
|
|||||||
public static bool CreateEmptyFile(string packageName, string packageVersion, string outputPath)
|
public static bool CreateEmptyFile(string packageName, string packageVersion, string outputPath)
|
||||||
{
|
{
|
||||||
// 创建内置清单实例
|
// 创建内置清单实例
|
||||||
var buildinFileCatalog = new BuiltinFileCatalog();
|
var buildinFileCatalog = new BuiltinCatalog();
|
||||||
buildinFileCatalog.FileVersion = BuiltinFileCatalogDefine.FileVersion;
|
buildinFileCatalog.FileVersion = BuiltinCatalogDefine.FileVersion;
|
||||||
buildinFileCatalog.PackageName = packageName;
|
buildinFileCatalog.PackageName = packageName;
|
||||||
buildinFileCatalog.PackageVersion = packageVersion;
|
buildinFileCatalog.PackageVersion = packageVersion;
|
||||||
|
|
||||||
// 创建输出文件
|
// 创建输出文件
|
||||||
string jsonFilePath = $"{outputPath}/{BuiltinFileCatalogDefine.JsonFileName}";
|
string jsonFilePath = $"{outputPath}/{BuiltinCatalogDefine.JsonFileName}";
|
||||||
if (File.Exists(jsonFilePath))
|
if (File.Exists(jsonFilePath))
|
||||||
File.Delete(jsonFilePath);
|
File.Delete(jsonFilePath);
|
||||||
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
SerializeToJson(jsonFilePath, buildinFileCatalog);
|
||||||
|
|
||||||
// 创建输出文件
|
// 创建输出文件
|
||||||
string binaryFilePath = $"{outputPath}/{BuiltinFileCatalogDefine.BinaryFileName}";
|
string binaryFilePath = $"{outputPath}/{BuiltinCatalogDefine.BinaryFileName}";
|
||||||
if (File.Exists(binaryFilePath))
|
if (File.Exists(binaryFilePath))
|
||||||
File.Delete(binaryFilePath);
|
File.Delete(binaryFilePath);
|
||||||
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
SerializeToBinary(binaryFilePath, buildinFileCatalog);
|
||||||
|
|
||||||
UnityEditor.AssetDatabase.Refresh();
|
UnityEditor.AssetDatabase.Refresh();
|
||||||
Debug.Log($"Succeed to save catalog file : {binaryFilePath}");
|
Debug.Log($"Successfully saved catalog file: {binaryFilePath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 序列化(JSON文件)
|
/// 序列化(JSON文件)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SerializeToJson(string savePath, BuiltinFileCatalog catalog)
|
public static void SerializeToJson(string savePath, BuiltinCatalog catalog)
|
||||||
{
|
{
|
||||||
string json = JsonUtility.ToJson(catalog, true);
|
string json = JsonUtility.ToJson(catalog, true);
|
||||||
FileUtility.WriteAllText(savePath, json);
|
FileUtility.WriteAllText(savePath, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反序列化(JSON文件)
|
|
||||||
/// </summary>
|
|
||||||
public static BuiltinFileCatalog DeserializeFromJson(string jsonContent)
|
|
||||||
{
|
|
||||||
return JsonUtility.FromJson<BuiltinFileCatalog>(jsonContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 序列化(二进制文件)
|
/// 序列化(二进制文件)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SerializeToBinary(string savePath, BuiltinFileCatalog catalog)
|
public static void SerializeToBinary(string savePath, BuiltinCatalog catalog)
|
||||||
{
|
{
|
||||||
using (FileStream fs = new FileStream(savePath, FileMode.Create))
|
using (FileStream fs = new FileStream(savePath, FileMode.Create))
|
||||||
{
|
{
|
||||||
// 创建缓存器
|
// 创建缓存器
|
||||||
BufferWriter buffer = new BufferWriter(BuiltinFileCatalogDefine.FileMaxSize);
|
BufferWriter buffer = new BufferWriter(BuiltinCatalogDefine.MaxFileSize);
|
||||||
|
|
||||||
// 写入文件标记
|
// 写入文件标记
|
||||||
buffer.WriteUInt32(BuiltinFileCatalogDefine.FileSign);
|
buffer.WriteUInt32(BuiltinCatalogDefine.FileHeader);
|
||||||
|
|
||||||
// 写入文件版本
|
// 写入文件版本
|
||||||
buffer.WriteUTF8(BuiltinFileCatalogDefine.FileVersion);
|
buffer.WriteUTF8(BuiltinCatalogDefine.FileVersion);
|
||||||
|
|
||||||
// 写入文件头信息
|
// 写入文件头信息
|
||||||
buffer.WriteUTF8(catalog.PackageName);
|
buffer.WriteUTF8(catalog.PackageName);
|
||||||
buffer.WriteUTF8(catalog.PackageVersion);
|
buffer.WriteUTF8(catalog.PackageVersion);
|
||||||
|
|
||||||
// 写入资源包列表
|
// 写入资源包列表
|
||||||
buffer.WriteInt32(catalog.Wrappers.Count);
|
buffer.WriteInt32(catalog.FileEntries.Count);
|
||||||
for (int i = 0; i < catalog.Wrappers.Count; i++)
|
for (int i = 0; i < catalog.FileEntries.Count; i++)
|
||||||
{
|
{
|
||||||
var fileWrapper = catalog.Wrappers[i];
|
var fileWrapper = catalog.FileEntries[i];
|
||||||
buffer.WriteUTF8(fileWrapper.BundleGUID);
|
buffer.WriteUTF8(fileWrapper.BundleGUID);
|
||||||
buffer.WriteUTF8(fileWrapper.FileName);
|
buffer.WriteUTF8(fileWrapper.FileName);
|
||||||
}
|
}
|
||||||
@@ -199,11 +193,20 @@ namespace YooAsset
|
|||||||
fs.Flush();
|
fs.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 反序列化(JSON文件)
|
||||||
|
/// </summary>
|
||||||
|
public static BuiltinCatalog DeserializeFromJson(string jsonContent)
|
||||||
|
{
|
||||||
|
return JsonUtility.FromJson<BuiltinCatalog>(jsonContent);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 反序列化(二进制文件)
|
/// 反序列化(二进制文件)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static BuiltinFileCatalog DeserializeFromBinary(byte[] binaryData)
|
public static BuiltinCatalog DeserializeFromBinary(byte[] binaryData)
|
||||||
{
|
{
|
||||||
if (binaryData == null || binaryData.Length == 0)
|
if (binaryData == null || binaryData.Length == 0)
|
||||||
throw new Exception("Catalog file data is null or empty.");
|
throw new Exception("Catalog file data is null or empty.");
|
||||||
@@ -212,31 +215,31 @@ namespace YooAsset
|
|||||||
BufferReader buffer = new BufferReader(binaryData);
|
BufferReader buffer = new BufferReader(binaryData);
|
||||||
|
|
||||||
// 读取文件标记
|
// 读取文件标记
|
||||||
uint fileSign = buffer.ReadUInt32();
|
uint fileHeader = buffer.ReadUInt32();
|
||||||
if (fileSign != BuiltinFileCatalogDefine.FileSign)
|
if (fileHeader != BuiltinCatalogDefine.FileHeader)
|
||||||
throw new Exception("Invalid catalog file.");
|
throw new Exception("Invalid catalog file.");
|
||||||
|
|
||||||
// 读取文件版本
|
// 读取文件版本
|
||||||
string fileVersion = buffer.ReadUTF8();
|
string fileVersion = buffer.ReadUTF8();
|
||||||
if (fileVersion != BuiltinFileCatalogDefine.FileVersion)
|
if (fileVersion != BuiltinCatalogDefine.FileVersion)
|
||||||
throw new Exception($"The catalog file version are not compatible : {fileVersion} != {BuiltinFileCatalogDefine.FileVersion}");
|
throw new Exception($"The catalog file version is not compatible: {fileVersion} != {BuiltinCatalogDefine.FileVersion}");
|
||||||
|
|
||||||
BuiltinFileCatalog catalog = new BuiltinFileCatalog();
|
BuiltinCatalog catalog = new BuiltinCatalog();
|
||||||
{
|
{
|
||||||
// 读取文件头信息
|
// 读取文件头信息
|
||||||
catalog.FileVersion = fileVersion;
|
catalog.FileVersion = fileVersion;
|
||||||
catalog.PackageName = buffer.ReadUTF8();
|
catalog.PackageName = buffer.ReadUTF8();
|
||||||
catalog.PackageVersion = buffer.ReadUTF8();
|
catalog.PackageVersion = buffer.ReadUTF8();
|
||||||
|
|
||||||
// 读取资源包列表
|
// 读取文件条目列表
|
||||||
int fileCount = buffer.ReadInt32();
|
int fileCount = buffer.ReadInt32();
|
||||||
catalog.Wrappers = new List<BuiltinFileCatalog.FileWrapper>(fileCount);
|
catalog.FileEntries = new List<BuiltinCatalog.FileEntry>(fileCount);
|
||||||
for (int i = 0; i < fileCount; i++)
|
for (int i = 0; i < fileCount; i++)
|
||||||
{
|
{
|
||||||
var fileWrapper = new BuiltinFileCatalog.FileWrapper();
|
var fileEntry = new BuiltinCatalog.FileEntry();
|
||||||
fileWrapper.BundleGUID = buffer.ReadUTF8();
|
fileEntry.BundleGUID = buffer.ReadUTF8();
|
||||||
fileWrapper.FileName = buffer.ReadUTF8();
|
fileEntry.FileName = buffer.ReadUTF8();
|
||||||
catalog.Wrappers.Add(fileWrapper);
|
catalog.FileEntries.Add(fileEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存系统,用于管理 StreamingAssets 中的资源包
|
||||||
|
/// </summary>
|
||||||
internal class BuiltinFileCache : IFileCache
|
internal class BuiltinFileCache : IFileCache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存配置
|
||||||
|
/// </summary>
|
||||||
internal struct CacheConfig
|
internal struct CacheConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -18,14 +24,16 @@ namespace YooAsset
|
|||||||
public IBundleDecryptor RawBundleDecryptor { get; set; }
|
public IBundleDecryptor RawBundleDecryptor { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载后台接口
|
/// 下载后台
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDownloadBackend DownloadBackend { get; set; }
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, BuiltinFileCacheEntry> _caches = new Dictionary<string, BuiltinFileCacheEntry>(10000);
|
private readonly Dictionary<string, BuiltinFileCacheEntry> _cacheEntries = new Dictionary<string, BuiltinFileCacheEntry>(10000);
|
||||||
|
|
||||||
// 缓存配置
|
/// <summary>
|
||||||
|
/// 缓存配置
|
||||||
|
/// </summary>
|
||||||
internal readonly CacheConfig Config;
|
internal readonly CacheConfig Config;
|
||||||
|
|
||||||
#region 接口属性
|
#region 接口属性
|
||||||
@@ -51,7 +59,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _caches.Count;
|
return _cacheEntries.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +70,12 @@ namespace YooAsset
|
|||||||
public long SpaceOccupied { get; private set; }
|
public long SpaceOccupied { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建内置文件缓存系统实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packageName">包裹名称</param>
|
||||||
|
/// <param name="rootPath">缓存根目录</param>
|
||||||
|
/// <param name="config">缓存配置</param>
|
||||||
public BuiltinFileCache(string packageName, string rootPath, CacheConfig config)
|
public BuiltinFileCache(string packageName, string rootPath, CacheConfig config)
|
||||||
{
|
{
|
||||||
PackageName = packageName;
|
PackageName = packageName;
|
||||||
@@ -77,7 +91,7 @@ namespace YooAsset
|
|||||||
var operation = new BFCInitializeOperation(this);
|
var operation = new BFCInitializeOperation(this);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
public virtual FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCWriteCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
var operation = new FCWriteCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
@@ -87,12 +101,12 @@ namespace YooAsset
|
|||||||
var operation = new FCClearCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
var operation = new FCClearCacheCompleteOperation($"{nameof(BuiltinFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
public virtual FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCVerifyCacheCompleteOperation();
|
var operation = new FCVerifyCacheCompleteOperation();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||||
{
|
{
|
||||||
@@ -113,16 +127,16 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
public virtual bool IsCached(string bundleGUID)
|
public virtual bool IsCached(string bundleGUID)
|
||||||
{
|
{
|
||||||
return _caches.ContainsKey(bundleGUID);
|
return _cacheEntries.ContainsKey(bundleGUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 内部方法
|
#region 内部方法
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定缓存
|
/// 获取指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BuiltinFileCacheEntry GetEntry(string bundleGUID)
|
internal BuiltinFileCacheEntry GetEntry(string bundleGUID)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(bundleGUID, out BuiltinFileCacheEntry entry))
|
if (_cacheEntries.TryGetValue(bundleGUID, out BuiltinFileCacheEntry entry))
|
||||||
return entry;
|
return entry;
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
@@ -131,12 +145,12 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加指定缓存
|
/// 添加指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AddEntry(string bundleGUID, BuiltinFileCacheEntry entry)
|
internal void AddEntry(string bundleGUID, BuiltinFileCacheEntry cacheEntry)
|
||||||
{
|
{
|
||||||
if (_caches.ContainsKey(bundleGUID))
|
if (_cacheEntries.ContainsKey(bundleGUID))
|
||||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
throw new YooInternalException($"Cache entry already exists: {bundleGUID}");
|
||||||
|
|
||||||
_caches.Add(bundleGUID, entry);
|
_cacheEntries.Add(bundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -144,7 +158,7 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal string GetCatalogBinaryFileLoadPath()
|
internal string GetCatalogBinaryFileLoadPath()
|
||||||
{
|
{
|
||||||
return PathUtility.Combine(RootPath, BuiltinFileCatalogDefine.BinaryFileName);
|
return PathUtility.Combine(RootPath, BuiltinCatalogDefine.BinaryFileName);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存条目
|
||||||
|
/// </summary>
|
||||||
internal class BuiltinFileCacheEntry : ICacheEntry
|
internal class BuiltinFileCacheEntry : ICacheEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
public string BundleGUID { get; private set; }
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包文件路径
|
||||||
|
/// </summary>
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建内置文件缓存条目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="filePath">资源包文件路径</param>
|
||||||
public BuiltinFileCacheEntry(string bundleGUID, string filePath)
|
public BuiltinFileCacheEntry(string bundleGUID, string filePath)
|
||||||
{
|
{
|
||||||
BundleGUID = bundleGUID;
|
BundleGUID = bundleGUID;
|
||||||
|
|||||||
@@ -1,67 +1,77 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存初始化操作
|
||||||
|
/// </summary>
|
||||||
internal class BFCInitializeOperation : FCInitializeOperation
|
internal class BFCInitializeOperation : FCInitializeOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
LoadCatalogFile,
|
LoadCatalog,
|
||||||
RecordFiles,
|
RecordEntry,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly BuiltinFileCache _fileCache;
|
private readonly BuiltinFileCache _fileCache;
|
||||||
private LoadBuiltinCatalogFileOperation _loadBuiltinCatalogFileOp;
|
private LoadBuiltinCatalogOperation _loadBuiltinCatalogOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public BFCInitializeOperation(BuiltinFileCache cache)
|
public BFCInitializeOperation(BuiltinFileCache fileCache)
|
||||||
{
|
{
|
||||||
_fileCache = cache;
|
_fileCache = fileCache;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.LoadCatalogFile;
|
_steps = ESteps.LoadCatalog;
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.LoadCatalogFile)
|
if (_steps == ESteps.LoadCatalog)
|
||||||
{
|
{
|
||||||
if (_loadBuiltinCatalogFileOp == null)
|
if (_loadBuiltinCatalogOp == null)
|
||||||
{
|
{
|
||||||
_loadBuiltinCatalogFileOp = new LoadBuiltinCatalogFileOperation(_fileCache);
|
var options = new LoadBuiltinCatalogOptions();
|
||||||
_loadBuiltinCatalogFileOp.StartOperation();
|
options.PackageName = _fileCache.PackageName;
|
||||||
AddChildOperation(_loadBuiltinCatalogFileOp);
|
options.FilePath = _fileCache.GetCatalogBinaryFileLoadPath();
|
||||||
|
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
||||||
|
_loadBuiltinCatalogOp = new LoadBuiltinCatalogOperation(options);
|
||||||
|
_loadBuiltinCatalogOp.StartOperation();
|
||||||
|
AddChildOperation(_loadBuiltinCatalogOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadBuiltinCatalogFileOp.UpdateOperation();
|
_loadBuiltinCatalogOp.UpdateOperation();
|
||||||
if (_loadBuiltinCatalogFileOp.IsDone == false)
|
if (_loadBuiltinCatalogOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_loadBuiltinCatalogFileOp.Status == EOperationStatus.Succeeded)
|
if (_loadBuiltinCatalogOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
_steps = ESteps.RecordFiles;
|
_steps = ESteps.RecordEntry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _loadBuiltinCatalogFileOp.Error;
|
Error = _loadBuiltinCatalogOp.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.RecordFiles)
|
if (_steps == ESteps.RecordEntry)
|
||||||
{
|
{
|
||||||
var catalog = _loadBuiltinCatalogFileOp.Catalog;
|
var catalog = _loadBuiltinCatalogOp.Catalog;
|
||||||
foreach (var wrapper in catalog.Wrappers)
|
foreach (var fileEntry in catalog.FileEntries)
|
||||||
{
|
{
|
||||||
string filePath = PathUtility.Combine(_fileCache.RootPath, wrapper.FileName);
|
string filePath = PathUtility.Combine(_fileCache.RootPath, fileEntry.FileName);
|
||||||
var entry = new BuiltinFileCacheEntry(wrapper.BundleGUID, filePath);
|
var cacheEntry = new BuiltinFileCacheEntry(fileEntry.BundleGUID, filePath);
|
||||||
_fileCache.AddEntry(wrapper.BundleGUID, entry);
|
_fileCache.AddEntry(fileEntry.BundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存加载 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class BFCLoadAssetBundleOperation : FCLoadBundleOperation
|
internal class BFCLoadAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -38,7 +41,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -54,7 +57,7 @@ namespace YooAsset
|
|||||||
options.CacheName = _fileCache.GetType().Name;
|
options.CacheName = _fileCache.GetType().Name;
|
||||||
options.Bundle = _bundle;
|
options.Bundle = _bundle;
|
||||||
options.FilePath = _cacheEntry.FilePath;
|
options.FilePath = _cacheEntry.FilePath;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor;
|
||||||
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
|
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
|
||||||
_loadLocalAssetBundleOp.StartOperation();
|
_loadLocalAssetBundleOp.StartOperation();
|
||||||
AddChildOperation(_loadLocalAssetBundleOp);
|
AddChildOperation(_loadLocalAssetBundleOp);
|
||||||
@@ -70,7 +73,7 @@ namespace YooAsset
|
|||||||
if (_loadLocalAssetBundleOp.Status == EOperationStatus.Succeeded)
|
if (_loadLocalAssetBundleOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
if (_loadLocalAssetBundleOp.BundleResult == null)
|
if (_loadLocalAssetBundleOp.BundleResult == null)
|
||||||
throw new YooInternalException("Loaded asset bundle result is null.");
|
throw new YooInternalException("Loaded bundle result is null.");
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
@@ -90,6 +93,9 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内置文件缓存加载 RawBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class BFCLoadRawBundleOperation : FCLoadBundleOperation
|
internal class BFCLoadRawBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -127,7 +133,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -143,7 +149,7 @@ namespace YooAsset
|
|||||||
options.CacheName = _fileCache.GetType().Name;
|
options.CacheName = _fileCache.GetType().Name;
|
||||||
options.Bundle = _bundle;
|
options.Bundle = _bundle;
|
||||||
options.FilePath = _cacheEntry.FilePath;
|
options.FilePath = _cacheEntry.FilePath;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.RawBundleDecryptor = _fileCache.Config.RawBundleDecryptor;
|
||||||
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
|
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
|
||||||
_loadLocalRawBundleOp.StartOperation();
|
_loadLocalRawBundleOp.StartOperation();
|
||||||
AddChildOperation(_loadLocalRawBundleOp);
|
AddChildOperation(_loadLocalRawBundleOp);
|
||||||
@@ -159,8 +165,10 @@ namespace YooAsset
|
|||||||
if(_loadLocalRawBundleOp.Status == EOperationStatus.Succeeded)
|
if(_loadLocalRawBundleOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
if (_loadLocalRawBundleOp.BundleResult == null)
|
if (_loadLocalRawBundleOp.BundleResult == null)
|
||||||
throw new YooInternalException("Loaded raw bundle result is null.");
|
throw new YooInternalException("Loaded bundle result is null.");
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
BundleResult = _loadLocalRawBundleOp.BundleResult;
|
BundleResult = _loadLocalRawBundleOp.BundleResult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal sealed class LoadBuiltinCatalogFileOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
TryLoadFileData,
|
|
||||||
RequestFileData,
|
|
||||||
LoadCatalog,
|
|
||||||
CheckResut,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly BuiltinFileCache _fileCache;
|
|
||||||
private IDownloadBytesRequest _webDataRequestOp;
|
|
||||||
private byte[] _fileData;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 内置资源目录
|
|
||||||
/// </summary>
|
|
||||||
public BuiltinFileCatalog Catalog;
|
|
||||||
|
|
||||||
internal LoadBuiltinCatalogFileOperation(BuiltinFileCache fileCache)
|
|
||||||
{
|
|
||||||
_fileCache = fileCache;
|
|
||||||
}
|
|
||||||
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 = _fileCache.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 = _fileCache.GetCatalogBinaryFileLoadPath();
|
|
||||||
string url = DownloadSystemTools.ToLocalUrl(filePath);
|
|
||||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
|
||||||
_webDataRequestOp = _fileCache.Config.DownloadBackend.CreateBytesRequest(args);
|
|
||||||
_webDataRequestOp.SendRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_webDataRequestOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
|
||||||
{
|
|
||||||
_fileData = _webDataRequestOp.Result;
|
|
||||||
_steps = ESteps.LoadCatalog;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = _webDataRequestOp.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.LoadCatalog)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Catalog = BuiltinFileCatalogTools.DeserializeFromBinary(_fileData);
|
|
||||||
_steps = ESteps.CheckResut;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed to load catalog file : {ex.Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResut)
|
|
||||||
{
|
|
||||||
if (Catalog.PackageName != _fileCache.PackageName)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Catalog file package name {Catalog.PackageName} cannot match the file cache package name {_fileCache.PackageName}";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,44 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存系统,用于编辑器模式下的资源模拟加载
|
||||||
|
/// </summary>
|
||||||
internal class EditorFileCache : IFileCache
|
internal class EditorFileCache : IFileCache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存配置
|
||||||
|
/// </summary>
|
||||||
internal struct CacheConfig
|
internal struct CacheConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 虚拟下载模式,模拟资源下载流程
|
||||||
|
/// </summary>
|
||||||
public bool VirtualDownloadMode { get; set; }
|
public bool VirtualDownloadMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 虚拟WebGL模式
|
||||||
|
/// </summary>
|
||||||
public bool VirtualWebGLMode { get; set; }
|
public bool VirtualWebGLMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步模拟最小帧数
|
||||||
|
/// </summary>
|
||||||
public int AsyncSimulateMinFrame { get; set; }
|
public int AsyncSimulateMinFrame { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步模拟最大帧数
|
||||||
|
/// </summary>
|
||||||
public int AsyncSimulateMaxFrame { get; set; }
|
public int AsyncSimulateMaxFrame { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, EditorFileCacheEntry> _caches = new Dictionary<string, EditorFileCacheEntry>(10000);
|
private readonly Dictionary<string, EditorFileCacheEntry> _cacheEntries = new Dictionary<string, EditorFileCacheEntry>(10000);
|
||||||
|
|
||||||
// 缓存配置
|
/// <summary>
|
||||||
|
/// 缓存配置
|
||||||
|
/// </summary>
|
||||||
internal readonly CacheConfig Config;
|
internal readonly CacheConfig Config;
|
||||||
|
|
||||||
#region 接口属性
|
#region 接口属性
|
||||||
@@ -41,7 +64,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _caches.Count;
|
return _cacheEntries.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +75,12 @@ namespace YooAsset
|
|||||||
public long SpaceOccupied { get; private set; }
|
public long SpaceOccupied { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建编辑器文件缓存系统实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packageName">包裹名称</param>
|
||||||
|
/// <param name="rootPath">缓存根目录</param>
|
||||||
|
/// <param name="config">缓存配置</param>
|
||||||
public EditorFileCache(string packageName, string rootPath, CacheConfig config)
|
public EditorFileCache(string packageName, string rootPath, CacheConfig config)
|
||||||
{
|
{
|
||||||
PackageName = packageName;
|
PackageName = packageName;
|
||||||
@@ -67,7 +96,7 @@ namespace YooAsset
|
|||||||
var operation = new EFCInitializeOperation(this);
|
var operation = new EFCInitializeOperation(this);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
public virtual FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new EFCWriteCacheOperation(this, options);
|
var operation = new EFCWriteCacheOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
@@ -77,16 +106,16 @@ namespace YooAsset
|
|||||||
var operation = new FCClearCacheCompleteOperation();
|
var operation = new FCClearCacheCompleteOperation();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
public virtual FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCVerifyCacheCompleteOperation();
|
var operation = new FCVerifyCacheCompleteOperation();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
if (options.Bundle.BundleType == (int)EBundleType.VirtualBundle)
|
if (options.Bundle.BundleType == (int)EBundleType.VirtualBundle)
|
||||||
{
|
{
|
||||||
var operation = new EFCLoadVirtualBundleOperation(this, options.Bundle);
|
var operation = new EFCLoadBundleOperation(this, options.Bundle);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -99,32 +128,21 @@ namespace YooAsset
|
|||||||
public virtual bool IsCached(string bundleGUID)
|
public virtual bool IsCached(string bundleGUID)
|
||||||
{
|
{
|
||||||
if (Config.VirtualDownloadMode)
|
if (Config.VirtualDownloadMode)
|
||||||
return _caches.ContainsKey(bundleGUID);
|
return _cacheEntries.ContainsKey(bundleGUID);
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 内部方法
|
#region 内部方法
|
||||||
/// <summary>
|
|
||||||
/// 获取指定缓存
|
|
||||||
/// </summary>
|
|
||||||
public EditorFileCacheEntry GetEntry(string bundleGUID)
|
|
||||||
{
|
|
||||||
if (_caches.TryGetValue(bundleGUID, out EditorFileCacheEntry entry))
|
|
||||||
return entry;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加指定缓存
|
/// 添加指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AddEntry(string bundleGUID, EditorFileCacheEntry entry)
|
internal void AddEntry(string bundleGUID, EditorFileCacheEntry cacheEntry)
|
||||||
{
|
{
|
||||||
if (_caches.ContainsKey(bundleGUID))
|
if (_cacheEntries.ContainsKey(bundleGUID))
|
||||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
throw new YooInternalException($"Cache entry already exists: {bundleGUID}");
|
||||||
|
|
||||||
_caches.Add(bundleGUID, entry);
|
_cacheEntries.Add(bundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存条目
|
||||||
|
/// </summary>
|
||||||
internal class EditorFileCacheEntry : ICacheEntry
|
internal class EditorFileCacheEntry : ICacheEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
public string BundleGUID { get; private set; }
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包文件路径
|
||||||
|
/// </summary>
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建编辑器文件缓存条目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="filePath">资源包文件路径</param>
|
||||||
public EditorFileCacheEntry(string bundleGUID, string filePath)
|
public EditorFileCacheEntry(string bundleGUID, string filePath)
|
||||||
{
|
{
|
||||||
BundleGUID = bundleGUID;
|
BundleGUID = bundleGUID;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存初始化操作
|
||||||
|
/// </summary>
|
||||||
internal class EFCInitializeOperation : FCInitializeOperation
|
internal class EFCInitializeOperation : FCInitializeOperation
|
||||||
{
|
{
|
||||||
private readonly EditorFileCache _fileCache;
|
private readonly EditorFileCache _fileCache;
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal class EFCLoadVirtualBundleOperation : FCLoadBundleOperation
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存加载资源包操作
|
||||||
|
/// </summary>
|
||||||
|
internal class EFCLoadBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
LoadVirtualBundle,
|
CheckCache,
|
||||||
CheckResult,
|
LoadBundle,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,14 +19,14 @@ namespace YooAsset
|
|||||||
private int _asyncSimulateFrame;
|
private int _asyncSimulateFrame;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public EFCLoadVirtualBundleOperation(EditorFileCache fileCache, PackageBundle bundle)
|
public EFCLoadBundleOperation(EditorFileCache fileCache, PackageBundle bundle)
|
||||||
{
|
{
|
||||||
_fileCache = fileCache;
|
_fileCache = fileCache;
|
||||||
_bundle = bundle;
|
_bundle = bundle;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.LoadVirtualBundle;
|
_steps = ESteps.CheckCache;
|
||||||
_asyncSimulateFrame = GetAsyncSimulateFrame();
|
_asyncSimulateFrame = GetAsyncSimulateFrame();
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
@@ -31,21 +34,20 @@ namespace YooAsset
|
|||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.LoadVirtualBundle)
|
if (_steps == ESteps.CheckCache)
|
||||||
{
|
{
|
||||||
var entry = _fileCache.GetEntry(_bundle.BundleGUID);
|
if (_fileCache.IsCached(_bundle.BundleGUID) == false)
|
||||||
if (entry == null)
|
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_bundle.BundleGUID}";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_steps = ESteps.CheckResult;
|
_steps = ESteps.LoadBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResult)
|
if (_steps == ESteps.LoadBundle)
|
||||||
{
|
{
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
{
|
{
|
||||||
@@ -53,12 +55,15 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "WebGL mode only support asyn load method.";
|
Error = "WebGL mode only supports async load method.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
|
|
||||||
|
string editorFilePath = EditorFileSystemTools.GetEditorFilePath(_bundle);
|
||||||
|
BundleResult = new VirtualBundleResult(editorFilePath, _bundle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -68,6 +73,9 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
|
|
||||||
|
string editorFilePath = EditorFileSystemTools.GetEditorFilePath(_bundle);
|
||||||
|
BundleResult = new VirtualBundleResult(editorFilePath, _bundle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,44 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑器文件缓存写入操作
|
||||||
|
/// </summary>
|
||||||
internal class EFCWriteCacheOperation : FCWriteCacheOperation
|
internal class EFCWriteCacheOperation : FCWriteCacheOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Check,
|
CheckCache,
|
||||||
CacheFile,
|
CacheFile,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly EditorFileCache _cache;
|
private readonly EditorFileCache _fileCache;
|
||||||
private readonly WriteCacheOptions _options;
|
private readonly FCWriteCacheOptions _options;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public EFCWriteCacheOperation(EditorFileCache cache, WriteCacheOptions options)
|
public EFCWriteCacheOperation(EditorFileCache cache, FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = cache;
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.Check;
|
_steps = ESteps.CheckCache;
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.Check)
|
if (_steps == ESteps.CheckCache)
|
||||||
{
|
{
|
||||||
if (_cache.IsCached(_options.Bundle.BundleGUID))
|
if (_fileCache.IsCached(_options.Bundle.BundleGUID))
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "The bundle is cached.";
|
Error = "The bundle is already cached.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -48,7 +49,7 @@ namespace YooAsset
|
|||||||
if (_steps == ESteps.CacheFile)
|
if (_steps == ESteps.CacheFile)
|
||||||
{
|
{
|
||||||
var cacheEntry = new EditorFileCacheEntry(_options.Bundle.BundleGUID, _options.FilePath);
|
var cacheEntry = new EditorFileCacheEntry(_options.Bundle.BundleGUID, _options.FilePath);
|
||||||
_cache.AddEntry(_options.Bundle.BundleGUID, cacheEntry);
|
_fileCache.AddEntry(_options.Bundle.BundleGUID, cacheEntry);
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,13 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证异常
|
/// 验证异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Exception = -7,
|
Exception = -8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据无效
|
||||||
|
/// </summary>
|
||||||
|
BytesDataInvalid = -7,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 未找到缓存信息
|
/// 未找到缓存信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文件校验工具类
|
||||||
|
/// </summary>
|
||||||
internal class FileVerifyTools
|
internal class FileVerifyTools
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件校验
|
/// 校验文件完整性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="filePath">文件路径</param>
|
||||||
|
/// <param name="fileSize">期望的文件大小</param>
|
||||||
|
/// <param name="fileCRC">期望的文件CRC值</param>
|
||||||
|
/// <returns>校验结果</returns>
|
||||||
public static EFileVerifyResult FileVerify(string filePath, long fileSize, uint fileCRC)
|
public static EFileVerifyResult FileVerify(string filePath, long fileSize, uint fileCRC)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -15,7 +22,7 @@ namespace YooAsset
|
|||||||
if (File.Exists(filePath) == false)
|
if (File.Exists(filePath) == false)
|
||||||
return EFileVerifyResult.DataFileNotExisted;
|
return EFileVerifyResult.DataFileNotExisted;
|
||||||
|
|
||||||
// 验证文件大小
|
// 可选条件:验证文件大小
|
||||||
if (fileSize > 0)
|
if (fileSize > 0)
|
||||||
{
|
{
|
||||||
long size = FileUtility.GetFileSize(filePath);
|
long size = FileUtility.GetFileSize(filePath);
|
||||||
@@ -25,7 +32,7 @@ namespace YooAsset
|
|||||||
return EFileVerifyResult.FileOverflow;
|
return EFileVerifyResult.FileOverflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证文件CRC
|
// 可选条件:验证文件CRC
|
||||||
if (fileCRC > 0)
|
if (fileCRC > 0)
|
||||||
{
|
{
|
||||||
uint crc = HashUtility.ComputeFileCRC32AsUInt(filePath);
|
uint crc = HashUtility.ComputeFileCRC32AsUInt(filePath);
|
||||||
@@ -41,7 +48,52 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
YooLogger.Error($"File verify exception : {ex.Message}");
|
YooLogger.Error($"File verification exception: {ex.Message}");
|
||||||
|
return EFileVerifyResult.Exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 校验文件完整性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileData">文件数据</param>
|
||||||
|
/// <param name="fileSize">期望的文件大小</param>
|
||||||
|
/// <param name="fileCRC">期望的文件CRC值</param>
|
||||||
|
/// <returns>校验结果</returns>
|
||||||
|
public static EFileVerifyResult FileVerify(byte[] fileData, long fileSize, uint fileCRC)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (fileData == null || fileData.Length == 0)
|
||||||
|
return EFileVerifyResult.BytesDataInvalid;
|
||||||
|
|
||||||
|
// 可选条件:验证文件大小
|
||||||
|
if (fileSize > 0)
|
||||||
|
{
|
||||||
|
long size = fileData.Length;
|
||||||
|
if (size < fileSize)
|
||||||
|
return EFileVerifyResult.FileNotComplete;
|
||||||
|
else if (size > fileSize)
|
||||||
|
return EFileVerifyResult.FileOverflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选条件:验证文件CRC
|
||||||
|
if (fileCRC > 0)
|
||||||
|
{
|
||||||
|
uint crc = HashUtility.ComputeBytesCRC32AsUInt(fileData);
|
||||||
|
if (crc == fileCRC)
|
||||||
|
return EFileVerifyResult.Succeed;
|
||||||
|
else
|
||||||
|
return EFileVerifyResult.FileCrcError;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return EFileVerifyResult.Succeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
YooLogger.Error($"File verification exception: {ex.Message}");
|
||||||
return EFileVerifyResult.Exception;
|
return EFileVerifyResult.Exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal class ClearCacheFilesOperation : FCClearCacheOperation
|
/// <summary>
|
||||||
|
/// 清理缓存文件操作
|
||||||
|
/// </summary>
|
||||||
|
internal class ClearCacheFilesOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
@@ -13,14 +15,14 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _cache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private readonly List<string> _bundleGUIDs;
|
private readonly List<string> _bundleGUIDs;
|
||||||
private int _clearFileTotalCount;
|
private int _fileTotalCount;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public ClearCacheFilesOperation(SandboxFileCache cache, List<string> bundleGUIDs)
|
public ClearCacheFilesOperation(SandboxFileCache fileCache, List<string> bundleGUIDs)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = fileCache;
|
||||||
_bundleGUIDs = bundleGUIDs;
|
_bundleGUIDs = bundleGUIDs;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
@@ -41,7 +43,7 @@ namespace YooAsset
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearFileTotalCount = _bundleGUIDs.Count;
|
_fileTotalCount = _bundleGUIDs.Count;
|
||||||
_steps = ESteps.ClearCache;
|
_steps = ESteps.ClearCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,16 +52,16 @@ namespace YooAsset
|
|||||||
for (int i = _bundleGUIDs.Count - 1; i >= 0; i--)
|
for (int i = _bundleGUIDs.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
string bundleGUID = _bundleGUIDs[i];
|
string bundleGUID = _bundleGUIDs[i];
|
||||||
_cache.RemoveEntry(bundleGUID);
|
_fileCache.RemoveEntry(bundleGUID);
|
||||||
_bundleGUIDs.RemoveAt(i);
|
_bundleGUIDs.RemoveAt(i);
|
||||||
if (IsBusy)
|
if (IsBusy)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_clearFileTotalCount == 0)
|
if (_fileTotalCount == 0)
|
||||||
Progress = 1.0f;
|
Progress = 1.0f;
|
||||||
else
|
else
|
||||||
Progress = 1.0f - ((float)_bundleGUIDs.Count / _clearFileTotalCount);
|
Progress = 1.0f - ((float)_bundleGUIDs.Count / _fileTotalCount);
|
||||||
|
|
||||||
if (_bundleGUIDs.Count == 0)
|
if (_bundleGUIDs.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索缓存文件操作,扫描缓存目录中的文件
|
||||||
|
/// </summary>
|
||||||
internal sealed class SearchCacheFilesOperation : AsyncOperationBase
|
internal sealed class SearchCacheFilesOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -16,7 +18,7 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _cache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private IEnumerator<string> _filesEnumerator = null;
|
private IEnumerator<string> _filesEnumerator = null;
|
||||||
private double _verifyStartTime;
|
private double _verifyStartTime;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
@@ -24,12 +26,12 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 需要验证的元素
|
/// 需要验证的元素
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly List<VerifyFileInfo> Result = new List<VerifyFileInfo>(5000);
|
public readonly List<SearchFileInfo> Result = new List<SearchFileInfo>(5000);
|
||||||
|
|
||||||
|
|
||||||
internal SearchCacheFilesOperation(SandboxFileCache cache)
|
internal SearchCacheFilesOperation(SandboxFileCache fileCache)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = fileCache;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
@@ -42,9 +44,9 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.Prepare)
|
if (_steps == ESteps.Prepare)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(_cache.RootPath))
|
if (Directory.Exists(_fileCache.RootPath))
|
||||||
{
|
{
|
||||||
var directories = Directory.EnumerateDirectories(_cache.RootPath);
|
var directories = Directory.EnumerateDirectories(_fileCache.RootPath);
|
||||||
_filesEnumerator = directories.GetEnumerator();
|
_filesEnumerator = directories.GetEnumerator();
|
||||||
_verifyStartTime = TimeUtility.RealtimeSinceStartup;
|
_verifyStartTime = TimeUtility.RealtimeSinceStartup;
|
||||||
_steps = ESteps.SearchFiles;
|
_steps = ESteps.SearchFiles;
|
||||||
@@ -80,19 +82,19 @@ namespace YooAsset
|
|||||||
if (isFindItem == false)
|
if (isFindItem == false)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var rootFoder = _filesEnumerator.Current;
|
var rootFolder = _filesEnumerator.Current;
|
||||||
var childDirectories = Directory.EnumerateDirectories(rootFoder);
|
var childDirectories = Directory.EnumerateDirectories(rootFolder);
|
||||||
foreach (var chidDirectory in childDirectories)
|
foreach (var childDirectory in childDirectories)
|
||||||
{
|
{
|
||||||
string bundleGUID = Path.GetFileName(chidDirectory);
|
string bundleGUID = Path.GetFileName(childDirectory);
|
||||||
if (_cache.IsCached(bundleGUID))
|
if (_fileCache.IsCached(bundleGUID))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 创建验证元素类
|
// 创建验证元素类
|
||||||
string fileRootPath = chidDirectory;
|
string fileRootPath = childDirectory;
|
||||||
string dataFilePath = PathUtility.Combine(fileRootPath, SandboxFileCacheDefine.BundleDataFileName);
|
string dataFilePath = PathUtility.Combine(fileRootPath, SandboxFileCacheDefine.BundleDataFileName);
|
||||||
string infoFilePath = PathUtility.Combine(fileRootPath, SandboxFileCacheDefine.BundleInfoFileName);
|
string infoFilePath = PathUtility.Combine(fileRootPath, SandboxFileCacheDefine.BundleInfoFileName);
|
||||||
var element = new VerifyFileInfo(bundleGUID, fileRootPath, dataFilePath, infoFilePath);
|
var element = new SearchFileInfo(bundleGUID, fileRootPath, dataFilePath, infoFilePath);
|
||||||
Result.Add(element);
|
Result.Add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -7,7 +7,7 @@ using System.Threading;
|
|||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存文件验证(线程版)
|
/// 缓存文件验证(线程版),验证缓存目录中的文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class VerifyCacheFilesOperation : AsyncOperationBase
|
internal sealed class VerifyCacheFilesOperation : AsyncOperationBase
|
||||||
{
|
{
|
||||||
@@ -19,25 +19,25 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _cache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private readonly EFileVerifyLevel _verifyLevel;
|
private readonly EFileVerifyLevel _verifyLevel;
|
||||||
private readonly int _fileVerifyMaxConcurrency;
|
private readonly int _fileVerifyMaxConcurrency;
|
||||||
private readonly List<VerifyFileInfo> _waitingList;
|
private readonly List<SearchFileInfo> _pendingVerifyList;
|
||||||
private List<VerifyFileInfo> _verifyingList;
|
private List<SearchFileInfo> _activeVerifyList;
|
||||||
private int _verifyMaxNum;
|
private int _maxConcurrentVerifyCount;
|
||||||
private int _verifyTotalCount;
|
private int _verifyTotalCount;
|
||||||
private double _verifyStartTime;
|
private double _verifyStartTime;
|
||||||
private int _succeedCount;
|
private int _successCount;
|
||||||
private int _failedCount;
|
private int _failedCount;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
|
||||||
internal VerifyCacheFilesOperation(SandboxFileCache cache, EFileVerifyLevel verifyLevel, int fileVerifyMaxConcurrency, List<VerifyFileInfo> elements)
|
internal VerifyCacheFilesOperation(SandboxFileCache fileCache, EFileVerifyLevel verifyLevel, int fileVerifyMaxConcurrency, List<SearchFileInfo> elements)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = fileCache;
|
||||||
_verifyLevel = verifyLevel;
|
_verifyLevel = verifyLevel;
|
||||||
_fileVerifyMaxConcurrency = fileVerifyMaxConcurrency;
|
_fileVerifyMaxConcurrency = fileVerifyMaxConcurrency;
|
||||||
_waitingList = elements;
|
_pendingVerifyList = elements;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
@@ -52,44 +52,44 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
// 设置同时验证的最大数
|
// 设置同时验证的最大数
|
||||||
int processorCount = Environment.ProcessorCount * 2 + 1;
|
int processorCount = Environment.ProcessorCount * 2 + 1;
|
||||||
_verifyMaxNum = Math.Min(processorCount, _fileVerifyMaxConcurrency);
|
_maxConcurrentVerifyCount = Math.Min(processorCount, _fileVerifyMaxConcurrency);
|
||||||
if (_verifyMaxNum < 1)
|
if (_maxConcurrentVerifyCount < 1)
|
||||||
_verifyMaxNum = 1;
|
_maxConcurrentVerifyCount = 1;
|
||||||
|
|
||||||
YooLogger.Log($"Verify max concurrency : {_verifyMaxNum}");
|
YooLogger.Log($"Verify max concurrency : {_maxConcurrentVerifyCount}");
|
||||||
_verifyingList = new List<VerifyFileInfo>(_verifyMaxNum);
|
_activeVerifyList = new List<SearchFileInfo>(_maxConcurrentVerifyCount);
|
||||||
_verifyStartTime = TimeUtility.RealtimeSinceStartup;
|
_verifyStartTime = TimeUtility.RealtimeSinceStartup;
|
||||||
_verifyTotalCount = _waitingList.Count;
|
_verifyTotalCount = _pendingVerifyList.Count;
|
||||||
_steps = ESteps.UpdateVerify;
|
_steps = ESteps.UpdateVerify;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.UpdateVerify)
|
if (_steps == ESteps.UpdateVerify)
|
||||||
{
|
{
|
||||||
// 检测校验结果
|
// 检测校验结果
|
||||||
for (int i = _verifyingList.Count - 1; i >= 0; i--)
|
for (int i = _activeVerifyList.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var verifyElement = _verifyingList[i];
|
var verifyElement = _activeVerifyList[i];
|
||||||
int result = verifyElement.Result;
|
int resultCode = verifyElement.VerifyResultCode; //注意: 一次命令取值
|
||||||
if (result != 0)
|
if (resultCode != 0)
|
||||||
{
|
{
|
||||||
_verifyingList.RemoveAt(i);
|
_activeVerifyList.RemoveAt(i);
|
||||||
if (verifyElement.Result == (int)EFileVerifyResult.Succeed)
|
if (resultCode == (int)EFileVerifyResult.Succeed)
|
||||||
{
|
{
|
||||||
_succeedCount++;
|
_successCount++;
|
||||||
var cacheEntry = new SandboxFileCacheEntry(verifyElement.BundleGUID, verifyElement.InfoFilePath, verifyElement.DataFilePath);
|
var cacheEntry = new SandboxFileCacheEntry(verifyElement.BundleGUID, verifyElement.InfoFilePath, verifyElement.DataFilePath);
|
||||||
_cache.AddEntry(verifyElement.BundleGUID, cacheEntry);
|
_fileCache.AddEntry(verifyElement.BundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_failedCount++;
|
_failedCount++;
|
||||||
YooLogger.Warning($"Failed to verify file {verifyElement.Result} and delete files : {verifyElement.FolderPath}");
|
YooLogger.Warning($"File verification failed (code: {verifyElement.VerifyResultCode}). Deleting files: {verifyElement.FolderPath}");
|
||||||
verifyElement.DeleteFiles();
|
verifyElement.DeleteCacheFolder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Progress = GetProgress();
|
Progress = GetProgress();
|
||||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
if (_pendingVerifyList.Count == 0 && _activeVerifyList.Count == 0)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
@@ -97,21 +97,21 @@ namespace YooAsset
|
|||||||
YooLogger.Log($"Verify cache files elapsed time {costTime:f1} seconds");
|
YooLogger.Log($"Verify cache files elapsed time {costTime:f1} seconds");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
for (int i = _pendingVerifyList.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (IsBusy)
|
if (IsBusy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (_verifyingList.Count >= _verifyMaxNum)
|
if (_activeVerifyList.Count >= _maxConcurrentVerifyCount)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var element = _waitingList[i];
|
var element = _pendingVerifyList[i];
|
||||||
bool succeed = ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyFileInThread), element);
|
bool succeed = ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyFileInThread), element);
|
||||||
if (succeed == false)
|
if (succeed == false)
|
||||||
VerifyFileInThread(element);
|
VerifyFileInThread(element);
|
||||||
|
|
||||||
_waitingList.RemoveAt(i);
|
_pendingVerifyList.RemoveAt(i);
|
||||||
_verifyingList.Add(element);
|
_activeVerifyList.Add(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,17 +119,17 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
if (_verifyTotalCount == 0)
|
if (_verifyTotalCount == 0)
|
||||||
return 1f;
|
return 1f;
|
||||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
return (float)(_successCount + _failedCount) / _verifyTotalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证缓存文件(子线程内操作)
|
// 验证缓存文件(子线程内操作)
|
||||||
private void VerifyFileInThread(object obj)
|
private void VerifyFileInThread(object obj)
|
||||||
{
|
{
|
||||||
VerifyFileInfo element = (VerifyFileInfo)obj;
|
SearchFileInfo element = (SearchFileInfo)obj;
|
||||||
int verifyResult = (int)VerifyFile(element, _verifyLevel);
|
int verifyResultCode = (int)VerifyFile(element, _verifyLevel);
|
||||||
element.Result = verifyResult;
|
element.VerifyResultCode = verifyResultCode; //注意: 一次命令赋值
|
||||||
}
|
}
|
||||||
private EFileVerifyResult VerifyFile(VerifyFileInfo element, EFileVerifyLevel verifyLevel)
|
private EFileVerifyResult VerifyFile(SearchFileInfo element, EFileVerifyLevel verifyLevel)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -145,7 +145,6 @@ namespace YooAsset
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 解析信息文件填充验证数据
|
// 解析信息文件填充验证数据
|
||||||
// 注意:验证数据在后续流程会被使用。
|
|
||||||
byte[] binaryData = FileUtility.ReadAllBytes(element.InfoFilePath);
|
byte[] binaryData = FileUtility.ReadAllBytes(element.InfoFilePath);
|
||||||
BufferReader buffer = new BufferReader(binaryData);
|
BufferReader buffer = new BufferReader(binaryData);
|
||||||
uint dataFileCRC = buffer.ReadUInt32();
|
uint dataFileCRC = buffer.ReadUInt32();
|
||||||
@@ -161,7 +160,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
YooLogger.Error($"File verify exception : {ex.Message}");
|
YooLogger.Error($"File verification exception: {ex.Message}");
|
||||||
return EFileVerifyResult.Exception;
|
return EFileVerifyResult.Exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
@@ -49,11 +49,11 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.Waiting)
|
if (_steps == ESteps.Waiting)
|
||||||
{
|
{
|
||||||
int result = _element.Result;
|
int resultCode = _element.VerifyResultCode; //注意: 一次命令取值
|
||||||
if (result == 0)
|
if (resultCode == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VerifyResult = (EFileVerifyResult)result;
|
VerifyResult = (EFileVerifyResult)resultCode;
|
||||||
if (VerifyResult == EFileVerifyResult.Succeed)
|
if (VerifyResult == EFileVerifyResult.Succeed)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
@@ -63,21 +63,21 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Failed to verify file : {_element.TempFilePath} ErrorCode : {VerifyResult}";
|
Error = $"Failed to verify file: {_element.FilePath} ErrorCode: {VerifyResult}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal override void InternalWaitForCompletion()
|
internal override void InternalWaitForCompletion()
|
||||||
{
|
{
|
||||||
//TODO 等待子线程验证文件完毕,该操作会挂起主线程!
|
//注意: 等待子线程验证文件完毕,该操作会挂起主线程!
|
||||||
ExecuteUntilComplete();
|
ExecuteUntilComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyFileInThread(object obj)
|
private void VerifyFileInThread(object obj)
|
||||||
{
|
{
|
||||||
TempFileInfo element = (TempFileInfo)obj;
|
TempFileInfo element = (TempFileInfo)obj;
|
||||||
int result = (int)FileVerifyTools.FileVerify(element.TempFilePath, element.TempFileSize, element.TempFileCRC);
|
int resultCode = (int)FileVerifyTools.FileVerify(element.FilePath, element.FileSize, element.FileCRC);
|
||||||
element.Result = result;
|
element.VerifyResultCode = resultCode; //注意: 一次命令赋值
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,6 +77,9 @@ namespace YooAsset
|
|||||||
protected abstract bool ParseOptionsStep();
|
protected abstract bool ParseOptionsStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理所有沙盒缓存操作
|
||||||
|
/// </summary>
|
||||||
internal sealed class SFCClearAllCacheOperation : SFCClearCacheOperation
|
internal sealed class SFCClearAllCacheOperation : SFCClearCacheOperation
|
||||||
{
|
{
|
||||||
internal SFCClearAllCacheOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
internal SFCClearAllCacheOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
||||||
@@ -84,15 +87,18 @@ namespace YooAsset
|
|||||||
|
|
||||||
protected override bool ParseOptionsStep()
|
protected override bool ParseOptionsStep()
|
||||||
{
|
{
|
||||||
var allEntrys = _fileCache.GetAllEntries();
|
var allEntries = _fileCache.GetAllEntries();
|
||||||
_bundleGUIDs = new List<string>(allEntrys.Count);
|
_bundleGUIDs = new List<string>(allEntries.Count);
|
||||||
foreach (var entry in allEntrys)
|
foreach (var entry in allEntries)
|
||||||
{
|
{
|
||||||
_bundleGUIDs.Add(entry.BundleGUID);
|
_bundleGUIDs.Add(entry.BundleGUID);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 清理未使用的沙盒缓存操作
|
||||||
|
/// </summary>
|
||||||
internal sealed class SFCClearUnusedCacheOperation : SFCClearCacheOperation
|
internal sealed class SFCClearUnusedCacheOperation : SFCClearCacheOperation
|
||||||
{
|
{
|
||||||
internal SFCClearUnusedCacheOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
internal SFCClearUnusedCacheOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
||||||
@@ -104,13 +110,13 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "Can not found active package manifest.";
|
Error = "Active package manifest not found.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allEntrys = _fileCache.GetAllEntries();
|
var allEntries = _fileCache.GetAllEntries();
|
||||||
_bundleGUIDs = new List<string>(allEntrys.Count);
|
_bundleGUIDs = new List<string>(allEntries.Count);
|
||||||
foreach (var entry in allEntrys)
|
foreach (var entry in allEntries)
|
||||||
{
|
{
|
||||||
if (_options.Manifest.IsIncludeBundleFile(entry.BundleGUID) == false)
|
if (_options.Manifest.IsIncludeBundleFile(entry.BundleGUID) == false)
|
||||||
{
|
{
|
||||||
@@ -120,6 +126,9 @@ namespace YooAsset
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 按资源地址清理沙盒缓存操作
|
||||||
|
/// </summary>
|
||||||
internal sealed class SFCClearCacheByLocationsOperation : SFCClearCacheOperation
|
internal sealed class SFCClearCacheByLocationsOperation : SFCClearCacheOperation
|
||||||
{
|
{
|
||||||
internal SFCClearCacheByLocationsOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
internal SFCClearCacheByLocationsOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
||||||
@@ -131,7 +140,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "Can not found active package manifest.";
|
Error = "Active package manifest not found.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +163,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Invalid clear param : {_options.ClearParam.GetType().FullName}";
|
Error = $"Invalid clear param: {_options.ClearParam.GetType().FullName}";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +180,9 @@ namespace YooAsset
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 按标签清理沙盒缓存操作
|
||||||
|
/// </summary>
|
||||||
internal sealed class SFCClearCacheByTagsOperation : SFCClearCacheOperation
|
internal sealed class SFCClearCacheByTagsOperation : SFCClearCacheOperation
|
||||||
{
|
{
|
||||||
internal SFCClearCacheByTagsOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
internal SFCClearCacheByTagsOperation(SandboxFileCache fileCache, ClearCacheOptions options)
|
||||||
@@ -182,7 +194,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "Can not found active package manifest.";
|
Error = "Active package manifest not found.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,13 +217,13 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Invalid clear param : {_options.ClearParam.GetType().FullName}";
|
Error = $"Invalid clear param: {_options.ClearParam.GetType().FullName}";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allEntrys = _fileCache.GetAllEntries();
|
var allEntries = _fileCache.GetAllEntries();
|
||||||
_bundleGUIDs = new List<string>(allEntrys.Count);
|
_bundleGUIDs = new List<string>(allEntries.Count);
|
||||||
foreach (var entry in allEntrys)
|
foreach (var entry in allEntries)
|
||||||
{
|
{
|
||||||
if (_options.Manifest.TryGetPackageBundleByBundleGUID(entry.BundleGUID, out PackageBundle bundle))
|
if (_options.Manifest.TryGetPackageBundleByBundleGUID(entry.BundleGUID, out PackageBundle bundle))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存初始化操作
|
||||||
|
/// </summary>
|
||||||
internal class SFCInitializeOperation : FCInitializeOperation
|
internal class SFCInitializeOperation : FCInitializeOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -11,14 +14,14 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _cache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private SearchCacheFilesOperation _searchCacheFilesOp;
|
private SearchCacheFilesOperation _searchCacheFilesOp;
|
||||||
private VerifyCacheFilesOperation _verifyCacheFilesOp;
|
private VerifyCacheFilesOperation _verifyCacheFilesOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public SFCInitializeOperation(SandboxFileCache cache)
|
public SFCInitializeOperation(SandboxFileCache fileCache)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = fileCache;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
@@ -33,7 +36,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
if (_searchCacheFilesOp == null)
|
if (_searchCacheFilesOp == null)
|
||||||
{
|
{
|
||||||
_searchCacheFilesOp = new SearchCacheFilesOperation(_cache);
|
_searchCacheFilesOp = new SearchCacheFilesOperation(_fileCache);
|
||||||
_searchCacheFilesOp.StartOperation();
|
_searchCacheFilesOp.StartOperation();
|
||||||
AddChildOperation(_searchCacheFilesOp);
|
AddChildOperation(_searchCacheFilesOp);
|
||||||
}
|
}
|
||||||
@@ -43,14 +46,23 @@ namespace YooAsset
|
|||||||
if (_searchCacheFilesOp.IsDone == false)
|
if (_searchCacheFilesOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_steps = ESteps.VerifyCacheFiles;
|
if (_searchCacheFilesOp.Status == EOperationStatus.Succeeded)
|
||||||
|
{
|
||||||
|
_steps = ESteps.VerifyCacheFiles;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _searchCacheFilesOp.Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.VerifyCacheFiles)
|
if (_steps == ESteps.VerifyCacheFiles)
|
||||||
{
|
{
|
||||||
if (_verifyCacheFilesOp == null)
|
if (_verifyCacheFilesOp == null)
|
||||||
{
|
{
|
||||||
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_cache, _cache.Config.FileVerifyLevel, _cache.Config.FileVerifyMaxConcurrency, _searchCacheFilesOp.Result);
|
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_fileCache, _fileCache.Config.FileVerifyLevel, _fileCache.Config.FileVerifyMaxConcurrency, _searchCacheFilesOp.Result);
|
||||||
_verifyCacheFilesOp.StartOperation();
|
_verifyCacheFilesOp.StartOperation();
|
||||||
AddChildOperation(_verifyCacheFilesOp);
|
AddChildOperation(_verifyCacheFilesOp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存加载 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class SFCLoadAssetBundleOperation : FCLoadBundleOperation
|
internal class SFCLoadAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -44,7 +47,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -60,7 +63,7 @@ namespace YooAsset
|
|||||||
options.CacheName = _fileCache.GetType().Name;
|
options.CacheName = _fileCache.GetType().Name;
|
||||||
options.Bundle = _bundle;
|
options.Bundle = _bundle;
|
||||||
options.FilePath = _cacheEntry.DataFilePath;
|
options.FilePath = _cacheEntry.DataFilePath;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor;
|
||||||
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
|
_loadLocalAssetBundleOp = new LoadLocalAssetBundleOperation(options);
|
||||||
_loadLocalAssetBundleOp.StartOperation();
|
_loadLocalAssetBundleOp.StartOperation();
|
||||||
AddChildOperation(_loadLocalAssetBundleOp);
|
AddChildOperation(_loadLocalAssetBundleOp);
|
||||||
@@ -104,9 +107,9 @@ namespace YooAsset
|
|||||||
// 说明:在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
|
// 说明:在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
|
||||||
if (_verifyCacheOp == null)
|
if (_verifyCacheOp == null)
|
||||||
{
|
{
|
||||||
var options = new VerifyCacheOptions();
|
var options = new FCVerifyCacheOptions();
|
||||||
options.Bundle = _bundle;
|
options.Bundle = _bundle;
|
||||||
options.FailedDeleteCache = true;
|
options.DeleteCacheEntryOnFailure = true;
|
||||||
_verifyCacheOp = _fileCache.VerifyCacheAsync(options);
|
_verifyCacheOp = _fileCache.VerifyCacheAsync(options);
|
||||||
_verifyCacheOp.StartOperation();
|
_verifyCacheOp.StartOperation();
|
||||||
AddChildOperation(_verifyCacheOp);
|
AddChildOperation(_verifyCacheOp);
|
||||||
@@ -147,7 +150,7 @@ namespace YooAsset
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assetBundle = FallbackLoadDecryptAssetBundle(_fileCache.Config.AssetBundleFallbackDecryptor);
|
assetBundle = FallbackLoadEncryptedAssetBundle(_fileCache.Config.AssetBundleFallbackDecryptor);
|
||||||
if (assetBundle == null)
|
if (assetBundle == null)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
@@ -182,20 +185,21 @@ namespace YooAsset
|
|||||||
private AssetBundle FallbackLoadAssetBundle()
|
private AssetBundle FallbackLoadAssetBundle()
|
||||||
{
|
{
|
||||||
byte[] fileData = FileUtility.ReadAllBytes(_cacheEntry.DataFilePath);
|
byte[] fileData = FileUtility.ReadAllBytes(_cacheEntry.DataFilePath);
|
||||||
if (fileData == null || fileData.Length == 0)
|
|
||||||
return null;
|
|
||||||
return AssetBundle.LoadFromMemory(fileData);
|
return AssetBundle.LoadFromMemory(fileData);
|
||||||
}
|
}
|
||||||
private AssetBundle FallbackLoadDecryptAssetBundle(IBundleMemoryDecryptor decryptor)
|
private AssetBundle FallbackLoadEncryptedAssetBundle(IBundleMemoryDecryptor decryptor)
|
||||||
{
|
{
|
||||||
var args = new BundleDecryptArgs();
|
var args = new BundleDecryptArgs();
|
||||||
args.Bundle = _bundle;
|
args.Bundle = _bundle;
|
||||||
args.FilePath = _cacheEntry.DataFilePath;
|
args.FilePath = _cacheEntry.DataFilePath;
|
||||||
var binaryData = decryptor.GetDecryptData(args);
|
var fileData = decryptor.GetDecryptData(args);
|
||||||
return AssetBundle.LoadFromMemory(binaryData);
|
return AssetBundle.LoadFromMemory(fileData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存加载 RawBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class SFCLoadRawBundleOperation : FCLoadBundleOperation
|
internal class SFCLoadRawBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -234,7 +238,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -250,7 +254,7 @@ namespace YooAsset
|
|||||||
options.CacheName = _fileCache.GetType().Name;
|
options.CacheName = _fileCache.GetType().Name;
|
||||||
options.Bundle = _bundle;
|
options.Bundle = _bundle;
|
||||||
options.FilePath = _cacheEntry.DataFilePath;
|
options.FilePath = _cacheEntry.DataFilePath;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.RawBundleDecryptor = _fileCache.Config.RawBundleDecryptor;
|
||||||
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
|
_loadLocalRawBundleOp = new LoadLocalRawBundleOperation(options);
|
||||||
_loadLocalRawBundleOp.StartOperation();
|
_loadLocalRawBundleOp.StartOperation();
|
||||||
AddChildOperation(_loadLocalRawBundleOp);
|
AddChildOperation(_loadLocalRawBundleOp);
|
||||||
@@ -268,6 +272,8 @@ namespace YooAsset
|
|||||||
if (_loadLocalRawBundleOp.BundleResult == null)
|
if (_loadLocalRawBundleOp.BundleResult == null)
|
||||||
throw new YooInternalException("Loaded raw bundle result is null.");
|
throw new YooInternalException("Loaded raw bundle result is null.");
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
BundleResult = _loadLocalRawBundleOp.BundleResult;
|
BundleResult = _loadLocalRawBundleOp.BundleResult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存验证操作
|
||||||
|
/// </summary>
|
||||||
internal class SFCVerifyCacheOperation : FCVerifyCacheOperation
|
internal class SFCVerifyCacheOperation : FCVerifyCacheOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -12,11 +15,11 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _fileCache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private readonly VerifyCacheOptions _options;
|
private readonly FCVerifyCacheOptions _options;
|
||||||
private VerifyTempFileOperation _verifyOperation;
|
private VerifyTempFileOperation _verifyTempFileOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public SFCVerifyCacheOperation(SandboxFileCache cache, VerifyCacheOptions options)
|
public SFCVerifyCacheOperation(SandboxFileCache cache, FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
_fileCache = cache;
|
_fileCache = cache;
|
||||||
_options = options;
|
_options = options;
|
||||||
@@ -36,7 +39,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "Not found cached bundle.";
|
Error = "Cached bundle not found.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -46,23 +49,23 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.VerifyFile)
|
if (_steps == ESteps.VerifyFile)
|
||||||
{
|
{
|
||||||
if (_verifyOperation == null)
|
if (_verifyTempFileOp == null)
|
||||||
{
|
{
|
||||||
var entry = _fileCache.GetEntry(_options.Bundle.BundleGUID);
|
var entry = _fileCache.GetEntry(_options.Bundle.BundleGUID);
|
||||||
var element = new TempFileInfo(entry.DataFilePath, _options.Bundle.FileCRC, _options.Bundle.FileSize);
|
var element = new TempFileInfo(entry.DataFilePath, _options.Bundle.FileCRC, _options.Bundle.FileSize);
|
||||||
_verifyOperation = new VerifyTempFileOperation(element);
|
_verifyTempFileOp = new VerifyTempFileOperation(element);
|
||||||
_verifyOperation.StartOperation();
|
_verifyTempFileOp.StartOperation();
|
||||||
AddChildOperation(_verifyOperation);
|
AddChildOperation(_verifyTempFileOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
_verifyOperation.WaitForCompletion();
|
_verifyTempFileOp.WaitForCompletion();
|
||||||
|
|
||||||
_verifyOperation.UpdateOperation();
|
_verifyTempFileOp.UpdateOperation();
|
||||||
if (_verifyOperation.IsDone == false)
|
if (_verifyTempFileOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_verifyOperation.Status == EOperationStatus.Succeeded)
|
if (_verifyTempFileOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
@@ -71,11 +74,11 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _verifyOperation.Error;
|
Error = _verifyTempFileOp.Error;
|
||||||
|
|
||||||
if (_options.FailedDeleteCache)
|
if (_options.DeleteCacheEntryOnFailure)
|
||||||
{
|
{
|
||||||
YooLogger.Error($"Find corrupted bundle file and remove cache entry : {_options.Bundle.BundleGUID}");
|
YooLogger.Error($"Found corrupted bundle file. Removing cache entry: {_options.Bundle.BundleGUID}");
|
||||||
_fileCache.RemoveEntry(_options.Bundle.BundleGUID);
|
_fileCache.RemoveEntry(_options.Bundle.BundleGUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ using System.IO;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存写入操作
|
||||||
|
/// </summary>
|
||||||
internal class SFCWriteCacheOperation : FCWriteCacheOperation
|
internal class SFCWriteCacheOperation : FCWriteCacheOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -14,14 +17,14 @@ namespace YooAsset
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly SandboxFileCache _cache;
|
private readonly SandboxFileCache _fileCache;
|
||||||
private readonly WriteCacheOptions _options;
|
private readonly FCWriteCacheOptions _options;
|
||||||
private VerifyTempFileOperation _verifyOperation;
|
private VerifyTempFileOperation _verifyTempFileOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public SFCWriteCacheOperation(SandboxFileCache cache, WriteCacheOptions options)
|
public SFCWriteCacheOperation(SandboxFileCache fileCache, FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
_cache = cache;
|
_fileCache = fileCache;
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
@@ -35,11 +38,11 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.Check)
|
if (_steps == ESteps.Check)
|
||||||
{
|
{
|
||||||
if (_cache.IsCached(_options.Bundle.BundleGUID))
|
if (_fileCache.IsCached(_options.Bundle.BundleGUID))
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = "The bundle is cached.";
|
Error = "The bundle is already cached.";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -49,22 +52,22 @@ namespace YooAsset
|
|||||||
|
|
||||||
if (_steps == ESteps.VerifyFile)
|
if (_steps == ESteps.VerifyFile)
|
||||||
{
|
{
|
||||||
if (_verifyOperation == null)
|
if (_verifyTempFileOp == null)
|
||||||
{
|
{
|
||||||
var element = new TempFileInfo(_options.FilePath, _options.Bundle.FileCRC, _options.Bundle.FileSize);
|
var element = new TempFileInfo(_options.FilePath, _options.Bundle.FileCRC, _options.Bundle.FileSize);
|
||||||
_verifyOperation = new VerifyTempFileOperation(element);
|
_verifyTempFileOp = new VerifyTempFileOperation(element);
|
||||||
_verifyOperation.StartOperation();
|
_verifyTempFileOp.StartOperation();
|
||||||
AddChildOperation(_verifyOperation);
|
AddChildOperation(_verifyTempFileOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsWaitForCompletion)
|
if (IsWaitForCompletion)
|
||||||
_verifyOperation.WaitForCompletion();
|
_verifyTempFileOp.WaitForCompletion();
|
||||||
|
|
||||||
_verifyOperation.UpdateOperation();
|
_verifyTempFileOp.UpdateOperation();
|
||||||
if (_verifyOperation.IsDone == false)
|
if (_verifyTempFileOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_verifyOperation.Status == EOperationStatus.Succeeded)
|
if (_verifyTempFileOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
_steps = ESteps.CacheFile;
|
_steps = ESteps.CacheFile;
|
||||||
}
|
}
|
||||||
@@ -72,37 +75,45 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _verifyOperation.Error;
|
Error = _verifyTempFileOp.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.CacheFile)
|
if (_steps == ESteps.CacheFile)
|
||||||
{
|
{
|
||||||
string infoFilePath = _cache.GetInfoFilePath(_options.Bundle);
|
string dataFilePath = _fileCache.GetDataFilePath(_options.Bundle);
|
||||||
string dataFilePath = _cache.GetDataFilePath(_options.Bundle);
|
string infoFilePath = _fileCache.GetInfoFilePath(_options.Bundle);
|
||||||
|
string dataTempPath = _fileCache.GetDataTempFilePath(_options.Bundle);
|
||||||
|
string infoTempPath = _fileCache.GetInfoTempFilePath(_options.Bundle);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (File.Exists(infoFilePath))
|
// 阶段A:准备目标目录,清理可能存在的残留文件
|
||||||
File.Delete(infoFilePath);
|
|
||||||
if (File.Exists(dataFilePath))
|
|
||||||
File.Delete(dataFilePath);
|
|
||||||
|
|
||||||
// 拷贝数据文件
|
|
||||||
FileUtility.EnsureFileDirectory(dataFilePath);
|
FileUtility.EnsureFileDirectory(dataFilePath);
|
||||||
FileInfo fileInfo = new FileInfo(_options.FilePath);
|
DeleteFileSafely(dataTempPath);
|
||||||
fileInfo.CopyTo(dataFilePath, true);
|
DeleteFileSafely(infoTempPath);
|
||||||
|
|
||||||
// 写入信息文件
|
// 阶段B:写入临时文件
|
||||||
FileUtility.EnsureFileDirectory(infoFilePath);
|
FileInfo fileInfo = new FileInfo(_options.FilePath);
|
||||||
using (FileStream fs = new FileStream(infoFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
fileInfo.CopyTo(dataTempPath, true);
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(infoTempPath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||||
{
|
{
|
||||||
_cache.SharedBuffer.Clear();
|
var buffer = new BufferWriter(128);
|
||||||
_cache.SharedBuffer.WriteUInt32(_options.Bundle.FileCRC);
|
buffer.WriteUInt32(_options.Bundle.FileCRC);
|
||||||
_cache.SharedBuffer.WriteInt64(_options.Bundle.FileSize);
|
buffer.WriteInt64(_options.Bundle.FileSize);
|
||||||
_cache.SharedBuffer.WriteToStream(fs);
|
buffer.WriteToStream(fs);
|
||||||
fs.Flush();
|
fs.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 阶段C:原子提交
|
||||||
|
if (File.Exists(dataFilePath))
|
||||||
|
File.Delete(dataFilePath);
|
||||||
|
File.Move(dataTempPath, dataFilePath);
|
||||||
|
|
||||||
|
if (File.Exists(infoFilePath))
|
||||||
|
File.Delete(infoFilePath);
|
||||||
|
File.Move(infoTempPath, infoFilePath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -110,11 +121,16 @@ namespace YooAsset
|
|||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Failed to write cache file. Error: {ex.Message}";
|
Error = $"Failed to write cache file. Error: {ex.Message}";
|
||||||
YooLogger.Error(Error);
|
YooLogger.Error(Error);
|
||||||
return; //失败后直接返回
|
|
||||||
|
// 回滚:清理临时文件,正式文件不受影响
|
||||||
|
DeleteFileSafely(dataTempPath);
|
||||||
|
DeleteFileSafely(infoTempPath);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 阶段D:注册内存缓存条目
|
||||||
var cacheEntry = new SandboxFileCacheEntry(_options.Bundle.BundleGUID, infoFilePath, dataFilePath);
|
var cacheEntry = new SandboxFileCacheEntry(_options.Bundle.BundleGUID, infoFilePath, dataFilePath);
|
||||||
_cache.AddEntry(_options.Bundle.BundleGUID, cacheEntry);
|
_fileCache.AddEntry(_options.Bundle.BundleGUID, cacheEntry);
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
}
|
}
|
||||||
@@ -123,5 +139,18 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
ExecuteBatch();
|
ExecuteBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DeleteFileSafely(string filePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
File.Delete(filePath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
YooLogger.Warning($"Failed to delete file: {filePath} Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,14 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存系统,用于管理下载到本地的资源包缓存
|
||||||
|
/// </summary>
|
||||||
internal class SandboxFileCache : IFileCache
|
internal class SandboxFileCache : IFileCache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存配置
|
||||||
|
/// </summary>
|
||||||
internal struct CacheConfig
|
internal struct CacheConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -33,17 +39,16 @@ namespace YooAsset
|
|||||||
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; }
|
public IBundleMemoryDecryptor AssetBundleFallbackDecryptor { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int HashFolderLength = 2;
|
private const int HashFolderNameLength = 2;
|
||||||
private readonly Dictionary<string, SandboxFileCacheEntry> _caches = new Dictionary<string, SandboxFileCacheEntry>(10000);
|
private readonly Dictionary<string, SandboxFileCacheEntry> _cacheEntries = new Dictionary<string, SandboxFileCacheEntry>(10000);
|
||||||
private readonly Dictionary<string, string> _dataFilePathMapping = new Dictionary<string, string>(10000);
|
private readonly Dictionary<string, string> _dataFilePathMapping = new Dictionary<string, string>(10000);
|
||||||
private readonly Dictionary<string, string> _infoFilePathMapping = new Dictionary<string, string>(10000);
|
private readonly Dictionary<string, string> _infoFilePathMapping = new Dictionary<string, string>(10000);
|
||||||
|
|
||||||
// 缓存配置
|
/// <summary>
|
||||||
|
/// 缓存配置
|
||||||
|
/// </summary>
|
||||||
internal readonly CacheConfig Config;
|
internal readonly CacheConfig Config;
|
||||||
|
|
||||||
// 共享缓冲区
|
|
||||||
internal readonly BufferWriter SharedBuffer = new BufferWriter(1024);
|
|
||||||
|
|
||||||
#region 接口属性
|
#region 接口属性
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 包裹名称
|
/// 包裹名称
|
||||||
@@ -67,7 +72,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _caches.Count;
|
return _cacheEntries.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +83,12 @@ namespace YooAsset
|
|||||||
public long SpaceOccupied { get; private set; }
|
public long SpaceOccupied { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建沙盒文件缓存系统实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packageName">包裹名称</param>
|
||||||
|
/// <param name="rootPath">缓存根目录</param>
|
||||||
|
/// <param name="config">缓存配置</param>
|
||||||
public SandboxFileCache(string packageName, string rootPath, CacheConfig config)
|
public SandboxFileCache(string packageName, string rootPath, CacheConfig config)
|
||||||
{
|
{
|
||||||
PackageName = packageName;
|
PackageName = packageName;
|
||||||
@@ -93,7 +104,7 @@ namespace YooAsset
|
|||||||
var operation = new SFCInitializeOperation(this);
|
var operation = new SFCInitializeOperation(this);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
public virtual FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new SFCWriteCacheOperation(this, options);
|
var operation = new SFCWriteCacheOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
@@ -127,12 +138,12 @@ namespace YooAsset
|
|||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
public virtual FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new SFCVerifyCacheOperation(this, options);
|
var operation = new SFCVerifyCacheOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||||
{
|
{
|
||||||
@@ -153,7 +164,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
public virtual bool IsCached(string bundleGUID)
|
public virtual bool IsCached(string bundleGUID)
|
||||||
{
|
{
|
||||||
return _caches.ContainsKey(bundleGUID);
|
return _cacheEntries.ContainsKey(bundleGUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 内部方法
|
#region 内部方法
|
||||||
@@ -185,12 +196,30 @@ namespace YooAsset
|
|||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取 Bundle 数据临时文件路径
|
||||||
|
/// </summary>
|
||||||
|
internal string GetDataTempFilePath(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
string folderName = GetHashFolderName(bundle.FileHash);
|
||||||
|
return PathUtility.Combine(RootPath, folderName, bundle.BundleGUID, SandboxFileCacheDefine.BundleDataTempFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取 Bundle 信息临时文件路径
|
||||||
|
/// </summary>
|
||||||
|
internal string GetInfoTempFilePath(PackageBundle bundle)
|
||||||
|
{
|
||||||
|
string folderName = GetHashFolderName(bundle.FileHash);
|
||||||
|
return PathUtility.Combine(RootPath, folderName, bundle.BundleGUID, SandboxFileCacheDefine.BundleInfoTempFileName);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定缓存
|
/// 获取指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal SandboxFileCacheEntry GetEntry(string bundleGUID)
|
internal SandboxFileCacheEntry GetEntry(string bundleGUID)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(bundleGUID, out SandboxFileCacheEntry entry))
|
if (_cacheEntries.TryGetValue(bundleGUID, out SandboxFileCacheEntry entry))
|
||||||
return entry;
|
return entry;
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
@@ -201,19 +230,19 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal IReadOnlyCollection<SandboxFileCacheEntry> GetAllEntries()
|
internal IReadOnlyCollection<SandboxFileCacheEntry> GetAllEntries()
|
||||||
{
|
{
|
||||||
return _caches.Values;
|
return _cacheEntries.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加指定缓存
|
/// 添加指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AddEntry(string bundleGUID, SandboxFileCacheEntry entry)
|
internal void AddEntry(string bundleGUID, SandboxFileCacheEntry cacheEntry)
|
||||||
{
|
{
|
||||||
if (_caches.ContainsKey(bundleGUID))
|
if (_cacheEntries.ContainsKey(bundleGUID))
|
||||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
throw new YooInternalException($"Cache entry already exists: {bundleGUID}");
|
||||||
|
|
||||||
_caches.Add(bundleGUID, entry);
|
_cacheEntries.Add(bundleGUID, cacheEntry);
|
||||||
SpaceOccupied += entry.GetFileSize();
|
SpaceOccupied += cacheEntry.GetFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -221,9 +250,9 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal void RemoveEntry(string bundleGUID)
|
internal void RemoveEntry(string bundleGUID)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(bundleGUID, out SandboxFileCacheEntry entry))
|
if (_cacheEntries.TryGetValue(bundleGUID, out SandboxFileCacheEntry entry))
|
||||||
{
|
{
|
||||||
_caches.Remove(bundleGUID);
|
_cacheEntries.Remove(bundleGUID);
|
||||||
_dataFilePathMapping.Remove(bundleGUID);
|
_dataFilePathMapping.Remove(bundleGUID);
|
||||||
_infoFilePathMapping.Remove(bundleGUID);
|
_infoFilePathMapping.Remove(bundleGUID);
|
||||||
SpaceOccupied -= entry.GetFileSize();
|
SpaceOccupied -= entry.GetFileSize();
|
||||||
@@ -236,9 +265,9 @@ namespace YooAsset
|
|||||||
if (string.IsNullOrEmpty(fileHash))
|
if (string.IsNullOrEmpty(fileHash))
|
||||||
throw new YooInternalException();
|
throw new YooInternalException();
|
||||||
|
|
||||||
if (fileHash.Length <= HashFolderLength)
|
if (fileHash.Length <= HashFolderNameLength)
|
||||||
return fileHash;
|
return fileHash;
|
||||||
return fileHash.Substring(0, HashFolderLength);
|
return fileHash.Substring(0, HashFolderNameLength);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存常量定义
|
||||||
|
/// </summary>
|
||||||
internal class SandboxFileCacheDefine
|
internal class SandboxFileCacheDefine
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -12,5 +15,15 @@ namespace YooAsset
|
|||||||
/// 信息文件名称
|
/// 信息文件名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string BundleInfoFileName = "__info";
|
public const string BundleInfoFileName = "__info";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据临时文件名称
|
||||||
|
/// </summary>
|
||||||
|
public const string BundleDataTempFileName = "__data.tmp";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 信息临时文件名称
|
||||||
|
/// </summary>
|
||||||
|
public const string BundleInfoTempFileName = "__info.tmp";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,13 +3,35 @@ using System.IO;
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 沙盒文件缓存条目
|
||||||
|
/// </summary>
|
||||||
internal class SandboxFileCacheEntry : ICacheEntry
|
internal class SandboxFileCacheEntry : ICacheEntry
|
||||||
{
|
{
|
||||||
public string BundleGUID { get; private set; }
|
private long _fileSize = -1;
|
||||||
public string InfoFilePath { get; private set; }
|
|
||||||
public string DataFilePath { get; private set; }
|
|
||||||
private long _fileSize = 0;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 信息文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string InfoFilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string DataFilePath { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建沙盒文件缓存条目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="infoFilePath">信息文件路径</param>
|
||||||
|
/// <param name="dataFilePath">数据文件路径</param>
|
||||||
public SandboxFileCacheEntry(string bundleGUID, string infoFilePath, string dataFilePath)
|
public SandboxFileCacheEntry(string bundleGUID, string infoFilePath, string dataFilePath)
|
||||||
{
|
{
|
||||||
BundleGUID = bundleGUID;
|
BundleGUID = bundleGUID;
|
||||||
@@ -18,8 +40,9 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除记录文件
|
/// 删除缓存文件夹及其所有内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <returns>删除是否成功</returns>
|
||||||
public bool Delete()
|
public bool Delete()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -43,13 +66,14 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取缓存文件总大小
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>文件总大小(字节)</returns>
|
||||||
public long GetFileSize()
|
public long GetFileSize()
|
||||||
{
|
{
|
||||||
if (_fileSize == 0)
|
if (_fileSize < 0)
|
||||||
{
|
_fileSize = FileUtility.GetFileSize(DataFilePath);
|
||||||
_fileSize = FileUtility.GetFileSize(InfoFilePath);
|
|
||||||
_fileSize += FileUtility.GetFileSize(DataFilePath);
|
|
||||||
}
|
|
||||||
return _fileSize;
|
return _fileSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 搜索的文件信息,用于缓存文件校验流程
|
||||||
|
/// </summary>
|
||||||
|
internal class SearchFileInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存文件夹路径
|
||||||
|
/// </summary>
|
||||||
|
public string FolderPath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string DataFilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 信息文件路径
|
||||||
|
/// </summary>
|
||||||
|
public string InfoFilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证结果码(原子操作对象,用于线程安全)
|
||||||
|
/// </summary>
|
||||||
|
public volatile int VerifyResultCode = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建验证文件信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="folderPath">缓存文件夹路径</param>
|
||||||
|
/// <param name="dataFilePath">数据文件路径</param>
|
||||||
|
/// <param name="infoFilePath">信息文件路径</param>
|
||||||
|
public SearchFileInfo(string bundleGUID, string folderPath, string dataFilePath, string infoFilePath)
|
||||||
|
{
|
||||||
|
BundleGUID = bundleGUID;
|
||||||
|
FolderPath = folderPath;
|
||||||
|
DataFilePath = dataFilePath;
|
||||||
|
InfoFilePath = infoFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除缓存文件夹及其内容
|
||||||
|
/// </summary>
|
||||||
|
public void DeleteCacheFolder()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(FolderPath, true);
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
YooLogger.Warning($"Failed to delete cache bundle folder: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,42 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 临时的文件信息,用于存储待验证的下载文件
|
||||||
|
/// </summary>
|
||||||
internal class TempFileInfo
|
internal class TempFileInfo
|
||||||
{
|
{
|
||||||
public string TempFilePath { private set; get; }
|
/// <summary>
|
||||||
public uint TempFileCRC { private set; get; }
|
/// 临时文件路径
|
||||||
public long TempFileSize { private set; get; }
|
/// </summary>
|
||||||
|
public string FilePath { private set; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注意:原子操作对象
|
/// 文件CRC校验值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public volatile int Result = 0;
|
public uint FileCRC { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件大小(字节)
|
||||||
|
/// </summary>
|
||||||
|
public long FileSize { private set; get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证结果码(原子操作对象,用于线程安全)
|
||||||
|
/// </summary>
|
||||||
|
public volatile int VerifyResultCode = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建临时文件信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">临时文件路径</param>
|
||||||
|
/// <param name="fileCRC">文件CRC校验值</param>
|
||||||
|
/// <param name="fileSize">文件大小(字节)</param>
|
||||||
public TempFileInfo(string filePath, uint fileCRC, long fileSize)
|
public TempFileInfo(string filePath, uint fileCRC, long fileSize)
|
||||||
{
|
{
|
||||||
TempFilePath = filePath;
|
FilePath = filePath;
|
||||||
TempFileCRC = fileCRC;
|
FileCRC = fileCRC;
|
||||||
TempFileSize = fileSize;
|
FileSize = fileSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal class VerifyFileInfo
|
|
||||||
{
|
|
||||||
public string BundleGUID { get; private set; }
|
|
||||||
public string FolderPath { get; private set; }
|
|
||||||
public string DataFilePath { get; private set; }
|
|
||||||
public string InfoFilePath { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 注意:原子操作对象
|
|
||||||
/// </summary>
|
|
||||||
public volatile int Result = 0;
|
|
||||||
|
|
||||||
public VerifyFileInfo(string bundleGUID, string folderPath, string dataFilePath, string infoFilePath)
|
|
||||||
{
|
|
||||||
BundleGUID = bundleGUID;
|
|
||||||
FolderPath = folderPath;
|
|
||||||
DataFilePath = dataFilePath;
|
|
||||||
InfoFilePath = infoFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteFiles()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(FolderPath, true);
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
YooLogger.Warning($"Failed to delete cache bundle folder : {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0a0a41496ce76334a958424c79db1016
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 65bba40cd16af3a47bddda520ab51d6b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web远端文件缓存初始化操作
|
||||||
|
/// </summary>
|
||||||
internal class WRFCInitializeOperation : FCInitializeOperation
|
internal class WRFCInitializeOperation : FCInitializeOperation
|
||||||
{
|
{
|
||||||
private readonly WebRemoteFileCache _fileCache;
|
private readonly WebRemoteFileCache _fileCache;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web远端文件缓存加载 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class WRFCLoadAssetBundleOperation : FCLoadBundleOperation
|
internal class WRFCLoadAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -12,12 +15,12 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly WebRemoteFileCache _fileCache;
|
private readonly WebRemoteFileCache _fileCache;
|
||||||
private readonly LoadBundleOptions _options;
|
private readonly FCLoadBundleOptions _options;
|
||||||
private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
|
private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
|
||||||
private WebRemoteFileCacheEntry _cacheEntry;
|
private WebRemoteFileCacheEntry _cacheEntry;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public WRFCLoadAssetBundleOperation(WebRemoteFileCache fileCache, LoadBundleOptions options)
|
public WRFCLoadAssetBundleOperation(WebRemoteFileCache fileCache, FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
_fileCache = fileCache;
|
_fileCache = fileCache;
|
||||||
_options = options;
|
_options = options;
|
||||||
@@ -38,7 +41,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_options.Bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -55,8 +58,9 @@ namespace YooAsset
|
|||||||
options.Bundle = _options.Bundle;
|
options.Bundle = _options.Bundle;
|
||||||
options.MainURL = _cacheEntry.MainURL;
|
options.MainURL = _cacheEntry.MainURL;
|
||||||
options.FallbackURL = _cacheEntry.FallbackURL;
|
options.FallbackURL = _cacheEntry.FallbackURL;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor;
|
||||||
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
||||||
|
options.DownloadVerifyLevel = _fileCache.Config.DownloadVerifyLevel;
|
||||||
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
|
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
|
||||||
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
|
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
|
||||||
|
|
||||||
@@ -76,7 +80,7 @@ namespace YooAsset
|
|||||||
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
|
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
if (_loadWebAssetBundleOp.BundleResult == null)
|
if (_loadWebAssetBundleOp.BundleResult == null)
|
||||||
throw new YooInternalException("Loaded asset bundle result is null.");
|
throw new YooInternalException("Loaded bundle result is null.");
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
@@ -90,5 +94,15 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal override void InternalWaitForCompletion()
|
||||||
|
{
|
||||||
|
if (_steps != ESteps.Done)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"{nameof(WebRemoteFileCache)} not support sync load asset bundle.";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web远端文件缓存系统,用于从远程服务器加载资源
|
||||||
|
/// </summary>
|
||||||
internal class WebRemoteFileCache : IFileCache
|
internal class WebRemoteFileCache : IFileCache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web远端文件缓存配置
|
||||||
|
/// </summary>
|
||||||
internal struct CacheConfig
|
internal struct CacheConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -17,6 +23,11 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DisableUnityWebCache { get; set; }
|
public bool DisableUnityWebCache { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载数据校验级别
|
||||||
|
/// </summary>
|
||||||
|
public EFileVerifyLevel DownloadVerifyLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AssetBundle 解密器
|
/// AssetBundle 解密器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -33,9 +44,11 @@ namespace YooAsset
|
|||||||
public IDownloadBackend DownloadBackend { get; set; }
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, WebRemoteFileCacheEntry> _caches = new Dictionary<string, WebRemoteFileCacheEntry>(10000);
|
private readonly Dictionary<string, WebRemoteFileCacheEntry> _cacheEntries = new Dictionary<string, WebRemoteFileCacheEntry>(10000);
|
||||||
|
|
||||||
// 缓存配置
|
/// <summary>
|
||||||
|
/// 缓存配置
|
||||||
|
/// </summary>
|
||||||
internal readonly CacheConfig Config;
|
internal readonly CacheConfig Config;
|
||||||
|
|
||||||
#region 接口属性
|
#region 接口属性
|
||||||
@@ -61,7 +74,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return 0;
|
return _cacheEntries.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +85,12 @@ namespace YooAsset
|
|||||||
public long SpaceOccupied { get; private set; }
|
public long SpaceOccupied { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建Web远端文件缓存系统实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packageName">包裹名称</param>
|
||||||
|
/// <param name="rootPath">缓存根目录</param>
|
||||||
|
/// <param name="config">缓存配置</param>
|
||||||
public WebRemoteFileCache(string packageName, string rootPath, CacheConfig config)
|
public WebRemoteFileCache(string packageName, string rootPath, CacheConfig config)
|
||||||
{
|
{
|
||||||
PackageName = packageName;
|
PackageName = packageName;
|
||||||
@@ -87,7 +106,7 @@ namespace YooAsset
|
|||||||
var operation = new WRFCInitializeOperation(this);
|
var operation = new WRFCInitializeOperation(this);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
public virtual FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCWriteCacheCompleteOperation($"{nameof(WebRemoteFileCache)} is readonly.");
|
var operation = new FCWriteCacheCompleteOperation($"{nameof(WebRemoteFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
@@ -97,12 +116,12 @@ namespace YooAsset
|
|||||||
var operation = new FCClearCacheCompleteOperation($"{nameof(WebRemoteFileCache)} is readonly.");
|
var operation = new FCClearCacheCompleteOperation($"{nameof(WebRemoteFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
public virtual FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCVerifyCacheCompleteOperation();
|
var operation = new FCVerifyCacheCompleteOperation();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||||
{
|
{
|
||||||
@@ -111,7 +130,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string error = $"{nameof(WebServerFileCache)} not support load bundle type : {options.Bundle.BundleType}";
|
string error = $"{nameof(WebRemoteFileCache)} not support load bundle type : {options.Bundle.BundleType}";
|
||||||
var operation = new FCLoadBundleErrorOperation(error);
|
var operation = new FCLoadBundleErrorOperation(error);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
@@ -122,9 +141,12 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region 内部方法
|
#region 内部方法
|
||||||
public WebRemoteFileCacheEntry GetEntry(PackageBundle bundle)
|
/// <summary>
|
||||||
|
/// 获取或创建指定资源包的缓存条目
|
||||||
|
/// </summary>
|
||||||
|
internal WebRemoteFileCacheEntry GetEntry(PackageBundle bundle)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(bundle.BundleGUID, out WebRemoteFileCacheEntry entry))
|
if (_cacheEntries.TryGetValue(bundle.BundleGUID, out WebRemoteFileCacheEntry entry))
|
||||||
{
|
{
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@@ -133,7 +155,7 @@ namespace YooAsset
|
|||||||
string mainURL = Config.RemoteServices.GetRemoteMainURL(bundle.FileName);
|
string mainURL = Config.RemoteServices.GetRemoteMainURL(bundle.FileName);
|
||||||
string fallbackURL = Config.RemoteServices.GetRemoteFallbackURL(bundle.FileName);
|
string fallbackURL = Config.RemoteServices.GetRemoteFallbackURL(bundle.FileName);
|
||||||
var newEntry = new WebRemoteFileCacheEntry(bundle.BundleGUID, mainURL, fallbackURL);
|
var newEntry = new WebRemoteFileCacheEntry(bundle.BundleGUID, mainURL, fallbackURL);
|
||||||
_caches.Add(bundle.BundleGUID, newEntry);
|
_cacheEntries.Add(bundle.BundleGUID, newEntry);
|
||||||
return newEntry;
|
return newEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,32 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web远端文件缓存条目
|
||||||
|
/// </summary>
|
||||||
internal class WebRemoteFileCacheEntry : ICacheEntry
|
internal class WebRemoteFileCacheEntry : ICacheEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
public string BundleGUID { get; private set; }
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主下载地址
|
||||||
|
/// </summary>
|
||||||
public string MainURL { get; private set; }
|
public string MainURL { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 备用下载地址
|
||||||
|
/// </summary>
|
||||||
public string FallbackURL { get; private set; }
|
public string FallbackURL { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建Web远端文件缓存条目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="mainURL">主下载地址</param>
|
||||||
|
/// <param name="fallbackURL">备用下载地址</param>
|
||||||
public WebRemoteFileCacheEntry(string bundleGUID, string mainURL, string fallbackURL)
|
public WebRemoteFileCacheEntry(string bundleGUID, string mainURL, string fallbackURL)
|
||||||
{
|
{
|
||||||
BundleGUID = bundleGUID;
|
BundleGUID = bundleGUID;
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a72d34ce1de343d4291428371af736a5
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
internal sealed class LoadWebServerCatalogOperation : AsyncOperationBase
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
RequestFileData,
|
|
||||||
LoadCatalog,
|
|
||||||
CheckResut,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly WebServerFileCache _fileCache;
|
|
||||||
private IDownloadBytesRequest _webDataRequestOp;
|
|
||||||
private byte[] _fileData;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 内置资源目录
|
|
||||||
/// </summary>
|
|
||||||
public BuiltinFileCatalog Catalog;
|
|
||||||
|
|
||||||
internal LoadWebServerCatalogOperation(WebServerFileCache fileCache)
|
|
||||||
{
|
|
||||||
_fileCache = fileCache;
|
|
||||||
}
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.RequestFileData;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.RequestFileData)
|
|
||||||
{
|
|
||||||
if (_webDataRequestOp == null)
|
|
||||||
{
|
|
||||||
string filePath = _fileCache.GetCatalogBinaryFileLoadPath();
|
|
||||||
string url = DownloadSystemTools.ToLocalUrl(filePath);
|
|
||||||
var args = new DownloadDataRequestArgs(url, 60, 0);
|
|
||||||
_webDataRequestOp = _fileCache.Config.DownloadBackend.CreateBytesRequest(args);
|
|
||||||
_webDataRequestOp.SendRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_webDataRequestOp.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
|
||||||
{
|
|
||||||
_fileData = _webDataRequestOp.Result;
|
|
||||||
_steps = ESteps.LoadCatalog;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = _webDataRequestOp.Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.LoadCatalog)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Catalog = BuiltinFileCatalogTools.DeserializeFromBinary(_fileData);
|
|
||||||
_steps = ESteps.CheckResut;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed to load catalog file : {ex.Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResut)
|
|
||||||
{
|
|
||||||
if (Catalog.PackageName != _fileCache.PackageName)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Catalog file package name {Catalog.PackageName} cannot match the file cache package name {_fileCache.PackageName}";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web服务器文件缓存初始化操作
|
||||||
|
/// </summary>
|
||||||
internal class WSFCInitializeOperation : FCInitializeOperation
|
internal class WSFCInitializeOperation : FCInitializeOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
LoadCatalogFile,
|
LoadCatalog,
|
||||||
RecordFiles,
|
RecordEntry,
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly WebServerFileCache _fileCache;
|
private readonly WebServerFileCache _fileCache;
|
||||||
private LoadWebServerCatalogOperation _loadWebCatalogFileOp;
|
private LoadBuiltinCatalogOperation _loadBuiltinCatalogOp;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public WSFCInitializeOperation(WebServerFileCache cache)
|
public WSFCInitializeOperation(WebServerFileCache cache)
|
||||||
@@ -21,47 +24,54 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
internal override void InternalStart()
|
internal override void InternalStart()
|
||||||
{
|
{
|
||||||
_steps = ESteps.LoadCatalogFile;
|
_steps = ESteps.LoadCatalog;
|
||||||
}
|
}
|
||||||
internal override void InternalUpdate()
|
internal override void InternalUpdate()
|
||||||
{
|
{
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_steps == ESteps.LoadCatalogFile)
|
if (_steps == ESteps.LoadCatalog)
|
||||||
{
|
{
|
||||||
if (_loadWebCatalogFileOp == null)
|
if (_loadBuiltinCatalogOp == null)
|
||||||
{
|
{
|
||||||
_loadWebCatalogFileOp = new LoadWebServerCatalogOperation(_fileCache);
|
var options = new LoadBuiltinCatalogOptions();
|
||||||
_loadWebCatalogFileOp.StartOperation();
|
options.PackageName = _fileCache.PackageName;
|
||||||
AddChildOperation(_loadWebCatalogFileOp);
|
options.FilePath = _fileCache.GetCatalogBinaryFileLoadPath();
|
||||||
|
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
||||||
|
_loadBuiltinCatalogOp = new LoadBuiltinCatalogOperation(options);
|
||||||
|
_loadBuiltinCatalogOp.StartOperation();
|
||||||
|
AddChildOperation(_loadBuiltinCatalogOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadWebCatalogFileOp.UpdateOperation();
|
_loadBuiltinCatalogOp.UpdateOperation();
|
||||||
if (_loadWebCatalogFileOp.IsDone == false)
|
if (_loadBuiltinCatalogOp.IsDone == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_loadWebCatalogFileOp.Status == EOperationStatus.Succeeded)
|
if (_loadBuiltinCatalogOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
_steps = ESteps.RecordFiles;
|
_steps = ESteps.RecordEntry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = _loadWebCatalogFileOp.Error;
|
Error = _loadBuiltinCatalogOp.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_steps == ESteps.RecordFiles)
|
if (_steps == ESteps.RecordEntry)
|
||||||
{
|
{
|
||||||
var catalog = _loadWebCatalogFileOp.Catalog;
|
var catalog = _loadBuiltinCatalogOp.Catalog;
|
||||||
foreach (var wrapper in catalog.Wrappers)
|
foreach (var fileEntry in catalog.FileEntries)
|
||||||
{
|
{
|
||||||
string filePath = PathUtility.Combine(_fileCache.RootPath, wrapper.FileName);
|
string filePath = PathUtility.Combine(_fileCache.RootPath, fileEntry.FileName);
|
||||||
var entry = new WebServerFileCacheEntry(wrapper.BundleGUID, filePath);
|
var cacheEntry = new WebServerFileCacheEntry(fileEntry.BundleGUID, filePath);
|
||||||
_fileCache.AddEntry(wrapper.BundleGUID, entry);
|
_fileCache.AddEntry(fileEntry.BundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web服务器文件缓存加载 AssetBundle 操作
|
||||||
|
/// </summary>
|
||||||
internal class WSFCLoadAssetBundleOperation : FCLoadBundleOperation
|
internal class WSFCLoadAssetBundleOperation : FCLoadBundleOperation
|
||||||
{
|
{
|
||||||
private enum ESteps
|
private enum ESteps
|
||||||
@@ -12,12 +15,12 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly WebServerFileCache _fileCache;
|
private readonly WebServerFileCache _fileCache;
|
||||||
private readonly LoadBundleOptions _options;
|
private readonly FCLoadBundleOptions _options;
|
||||||
private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
|
private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
|
||||||
private WebServerFileCacheEntry _cacheEntry;
|
private WebServerFileCacheEntry _cacheEntry;
|
||||||
private ESteps _steps = ESteps.None;
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
public WSFCLoadAssetBundleOperation(WebServerFileCache fileCache, LoadBundleOptions options)
|
public WSFCLoadAssetBundleOperation(WebServerFileCache fileCache, FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
_fileCache = fileCache;
|
_fileCache = fileCache;
|
||||||
_options = options;
|
_options = options;
|
||||||
@@ -38,7 +41,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Failed;
|
Status = EOperationStatus.Failed;
|
||||||
Error = $"Not found file cache entry: {_options.Bundle.BundleGUID}";
|
Error = $"File cache entry not found: {_options.Bundle.BundleGUID}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -56,8 +59,9 @@ namespace YooAsset
|
|||||||
options.Bundle = _options.Bundle;
|
options.Bundle = _options.Bundle;
|
||||||
options.MainURL = url;
|
options.MainURL = url;
|
||||||
options.FallbackURL = url;
|
options.FallbackURL = url;
|
||||||
options.Decryptor = _fileCache.Config.AssetBundleDecryptor;
|
options.AssetBundleDecryptor = _fileCache.Config.AssetBundleDecryptor;
|
||||||
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
options.DownloadBackend = _fileCache.Config.DownloadBackend;
|
||||||
|
options.DownloadVerifyLevel = _fileCache.Config.DownloadVerifyLevel;
|
||||||
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
|
options.WatchdogTimeout = _fileCache.Config.WatchdogTimeout;
|
||||||
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
|
options.DisableUnityWebCache = _fileCache.Config.DisableUnityWebCache;
|
||||||
|
|
||||||
@@ -77,7 +81,7 @@ namespace YooAsset
|
|||||||
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
|
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
if (_loadWebAssetBundleOp.BundleResult == null)
|
if (_loadWebAssetBundleOp.BundleResult == null)
|
||||||
throw new YooInternalException("Loaded asset bundle result is null.");
|
throw new YooInternalException("Loaded bundle result is null.");
|
||||||
|
|
||||||
_steps = ESteps.Done;
|
_steps = ESteps.Done;
|
||||||
Status = EOperationStatus.Succeeded;
|
Status = EOperationStatus.Succeeded;
|
||||||
@@ -91,5 +95,15 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
internal override void InternalWaitForCompletion()
|
||||||
|
{
|
||||||
|
if (_steps != ESteps.Done)
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"{nameof(WebServerFileCache)} not support sync load asset bundle.";
|
||||||
|
YooLogger.Error(Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web服务器文件缓存系统,用于WebGL平台从服务器加载资源
|
||||||
|
/// </summary>
|
||||||
internal class WebServerFileCache : IFileCache
|
internal class WebServerFileCache : IFileCache
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web服务器文件缓存配置
|
||||||
|
/// </summary>
|
||||||
internal struct CacheConfig
|
internal struct CacheConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -17,20 +23,27 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DisableUnityWebCache { get; set; }
|
public bool DisableUnityWebCache { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 下载数据校验级别
|
||||||
|
/// </summary>
|
||||||
|
public EFileVerifyLevel DownloadVerifyLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AssetBundle 解密器
|
/// AssetBundle 解密器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBundleDecryptor AssetBundleDecryptor { get; set; }
|
public IBundleDecryptor AssetBundleDecryptor { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载后台接口
|
/// 下载后台
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDownloadBackend DownloadBackend { get; set; }
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, WebServerFileCacheEntry> _caches = new Dictionary<string, WebServerFileCacheEntry>(10000);
|
private readonly Dictionary<string, WebServerFileCacheEntry> _cacheEntries = new Dictionary<string, WebServerFileCacheEntry>(10000);
|
||||||
|
|
||||||
// 缓存配置
|
/// <summary>
|
||||||
|
/// 缓存配置
|
||||||
|
/// </summary>
|
||||||
internal readonly CacheConfig Config;
|
internal readonly CacheConfig Config;
|
||||||
|
|
||||||
#region 接口属性
|
#region 接口属性
|
||||||
@@ -56,7 +69,7 @@ namespace YooAsset
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _caches.Count;
|
return _cacheEntries.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +80,12 @@ namespace YooAsset
|
|||||||
public long SpaceOccupied { get; private set; }
|
public long SpaceOccupied { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建Web服务器文件缓存系统实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packageName">包裹名称</param>
|
||||||
|
/// <param name="rootPath">缓存根目录</param>
|
||||||
|
/// <param name="config">缓存配置</param>
|
||||||
public WebServerFileCache(string packageName, string rootPath, CacheConfig config)
|
public WebServerFileCache(string packageName, string rootPath, CacheConfig config)
|
||||||
{
|
{
|
||||||
PackageName = packageName;
|
PackageName = packageName;
|
||||||
@@ -82,7 +101,7 @@ namespace YooAsset
|
|||||||
var operation = new WSFCInitializeOperation(this);
|
var operation = new WSFCInitializeOperation(this);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCWriteCacheOperation WriteCacheAsync(WriteCacheOptions options)
|
public virtual FCWriteCacheOperation WriteCacheAsync(FCWriteCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCWriteCacheCompleteOperation($"{nameof(WebServerFileCache)} is readonly.");
|
var operation = new FCWriteCacheCompleteOperation($"{nameof(WebServerFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
@@ -92,12 +111,12 @@ namespace YooAsset
|
|||||||
var operation = new FCClearCacheCompleteOperation($"{nameof(WebServerFileCache)} is readonly.");
|
var operation = new FCClearCacheCompleteOperation($"{nameof(WebServerFileCache)} is readonly.");
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCVerifyCacheOperation VerifyCacheAsync(VerifyCacheOptions options)
|
public virtual FCVerifyCacheOperation VerifyCacheAsync(FCVerifyCacheOptions options)
|
||||||
{
|
{
|
||||||
var operation = new FCVerifyCacheCompleteOperation();
|
var operation = new FCVerifyCacheCompleteOperation();
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FCLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FCLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
if (options.Bundle.BundleType == (int)EBundleType.AssetBundle)
|
||||||
{
|
{
|
||||||
@@ -113,13 +132,16 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
public virtual bool IsCached(string bundleGUID)
|
public virtual bool IsCached(string bundleGUID)
|
||||||
{
|
{
|
||||||
return _caches.ContainsKey(bundleGUID);
|
return _cacheEntries.ContainsKey(bundleGUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 内部方法
|
#region 内部方法
|
||||||
public WebServerFileCacheEntry GetEntry(string bundleGUID)
|
/// <summary>
|
||||||
|
/// 获取指定缓存条目
|
||||||
|
/// </summary>
|
||||||
|
internal WebServerFileCacheEntry GetEntry(string bundleGUID)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(bundleGUID, out WebServerFileCacheEntry entry))
|
if (_cacheEntries.TryGetValue(bundleGUID, out WebServerFileCacheEntry entry))
|
||||||
return entry;
|
return entry;
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
@@ -128,12 +150,12 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加指定缓存
|
/// 添加指定缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void AddEntry(string bundleGUID, WebServerFileCacheEntry entry)
|
internal void AddEntry(string bundleGUID, WebServerFileCacheEntry cacheEntry)
|
||||||
{
|
{
|
||||||
if (_caches.ContainsKey(bundleGUID))
|
if (_cacheEntries.ContainsKey(bundleGUID))
|
||||||
throw new YooInternalException($"Cache entry already existed: {bundleGUID}");
|
throw new YooInternalException($"Cache entry already exists: {bundleGUID}");
|
||||||
|
|
||||||
_caches.Add(bundleGUID, entry);
|
_cacheEntries.Add(bundleGUID, cacheEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -141,7 +163,7 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal string GetCatalogBinaryFileLoadPath()
|
internal string GetCatalogBinaryFileLoadPath()
|
||||||
{
|
{
|
||||||
return PathUtility.Combine(RootPath, BuiltinFileCatalogDefine.BinaryFileName);
|
return PathUtility.Combine(RootPath, BuiltinCatalogDefine.BinaryFileName);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Web服务器文件缓存条目
|
||||||
|
/// </summary>
|
||||||
internal class WebServerFileCacheEntry : ICacheEntry
|
internal class WebServerFileCacheEntry : ICacheEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包唯一标识
|
||||||
|
/// </summary>
|
||||||
public string BundleGUID { get; private set; }
|
public string BundleGUID { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包文件路径
|
||||||
|
/// </summary>
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建Web服务器文件缓存条目
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bundleGUID">资源包唯一标识</param>
|
||||||
|
/// <param name="filePath">资源包文件路径</param>
|
||||||
public WebServerFileCacheEntry(string bundleGUID, string filePath)
|
public WebServerFileCacheEntry(string bundleGUID, string filePath)
|
||||||
{
|
{
|
||||||
BundleGUID = bundleGUID;
|
BundleGUID = bundleGUID;
|
||||||
|
|||||||
@@ -1,254 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(非加密)
|
|
||||||
/// 通用实现,适用于 BuiltinFileSystem 和 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public class DefaultLoadAssetBundleOperation : LoadAssetBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
LoadAssetBundle,
|
|
||||||
CheckResult,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private AssetBundleCreateRequest _createRequest;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public DefaultLoadAssetBundleOperation(LoadAssetBundleOptions opionts) : base(opionts) { }
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.LoadAssetBundle;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_steps == ESteps.LoadAssetBundle)
|
|
||||||
{
|
|
||||||
if (IsWaitForCompletion)
|
|
||||||
Result = AssetBundle.LoadFromFile(_options.FileLoadPath);
|
|
||||||
else
|
|
||||||
_createRequest = AssetBundle.LoadFromFileAsync(_options.FileLoadPath);
|
|
||||||
|
|
||||||
_steps = ESteps.CheckResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.CheckResult)
|
|
||||||
{
|
|
||||||
if (_createRequest != null)
|
|
||||||
{
|
|
||||||
if (IsWaitForCompletion)
|
|
||||||
{
|
|
||||||
// 强制挂起主线程(注意:该操作会很耗时)
|
|
||||||
YooLogger.Warning("Suspend the main thread to load unity bundle.");
|
|
||||||
Result = _createRequest.assetBundle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_createRequest.isDone == false)
|
|
||||||
return;
|
|
||||||
Result = _createRequest.assetBundle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Result == null)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed to load asset bundle file : {_options.Bundle.BundleName}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal override void InternalWaitForCompletion()
|
|
||||||
{
|
|
||||||
ExecuteBatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override AssetBundle LoadFromMemory()
|
|
||||||
{
|
|
||||||
if (IsSupportFileIO(_options.FileLoadPath) == false)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
byte[] fileData = FileUtility.ReadAllBytes(_options.FileLoadPath);
|
|
||||||
if (fileData == null || fileData.Length == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return AssetBundle.LoadFromMemory(fileData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(加密)
|
|
||||||
/// 通用实现,适用于 BuiltinFileSystem 和 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DefaultLoadAssetBundleFromOffsetOperation : LoadAssetBundleOperation
|
|
||||||
{
|
|
||||||
protected DefaultLoadAssetBundleFromOffsetOperation(LoadAssetBundleOptions options) : base(options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取偏移值
|
|
||||||
/// </summary>
|
|
||||||
protected abstract uint GetFileOffset();
|
|
||||||
|
|
||||||
public override AssetBundle LoadFromMemory()
|
|
||||||
{
|
|
||||||
int offset = (int)GetFileOffset();
|
|
||||||
byte[] fileData = File.ReadAllBytes(_options.FileLoadPath);
|
|
||||||
if (fileData == null || fileData.Length <= offset)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// 跳过偏移量
|
|
||||||
byte[] bundleData = new byte[fileData.Length - offset];
|
|
||||||
Buffer.BlockCopy(fileData, offset, bundleData, 0, bundleData.Length);
|
|
||||||
|
|
||||||
return AssetBundle.LoadFromMemory(bundleData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(加密)
|
|
||||||
/// 通用实现,适用于 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DefaultLoadAssetBundleFromMemoryOperation : LoadAssetBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CheckFilePath,
|
|
||||||
LoadAssetBundle,
|
|
||||||
CheckResult,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private AssetBundleCreateRequest _createRequest;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public DefaultLoadAssetBundleFromMemoryOperation(LoadAssetBundleOptions options) : base(options) { }
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.CheckFilePath;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.CheckFilePath)
|
|
||||||
{
|
|
||||||
string filePath = _options.FileLoadPath;
|
|
||||||
if (IsSupportFileIO(filePath) == false)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"FileIO not supported for builtin path : {filePath}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.LoadAssetBundle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_steps == ESteps.LoadAssetBundle)
|
|
||||||
{
|
|
||||||
byte[] fileData = File.ReadAllBytes(_options.FileLoadPath);
|
|
||||||
byte[] rawData = DecryptData(fileData);
|
|
||||||
if (rawData == null || rawData.Length == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.None;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = "Decrypted raw data is null or empty.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsWaitForCompletion)
|
|
||||||
Result = AssetBundle.LoadFromMemory(rawData);
|
|
||||||
else
|
|
||||||
_createRequest = AssetBundle.LoadFromMemoryAsync(rawData);
|
|
||||||
|
|
||||||
_steps = ESteps.CheckResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文件数据解密
|
|
||||||
/// </summary>
|
|
||||||
protected abstract byte[] DecryptData(byte[] data);
|
|
||||||
|
|
||||||
public override AssetBundle LoadFromMemory()
|
|
||||||
{
|
|
||||||
byte[] fileData = File.ReadAllBytes(_options.FileLoadPath);
|
|
||||||
byte[] rawData = DecryptData(fileData);
|
|
||||||
if (rawData == null || rawData.Length == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return AssetBundle.LoadFromMemory(rawData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(加密)
|
|
||||||
/// 通用实现,适用于 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DefaultLoadAssetBundleFromStreamOperation : LoadAssetBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CheckFilePath,
|
|
||||||
LoadAssetBundle,
|
|
||||||
CheckResult,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
protected DefaultLoadAssetBundleFromStreamOperation(LoadAssetBundleOptions options) : base(options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.CheckFilePath)
|
|
||||||
{
|
|
||||||
string filePath = _options.FileLoadPath;
|
|
||||||
if (IsSupportFileIO(filePath) == false)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"FileIO not supported for builtin path : {filePath}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.LoadAssetBundle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文件数据解密
|
|
||||||
/// </summary>
|
|
||||||
protected abstract byte[] DecryptData(byte[] data);
|
|
||||||
|
|
||||||
public override AssetBundle LoadFromMemory()
|
|
||||||
{
|
|
||||||
byte[] fileData = File.ReadAllBytes(_options.FileLoadPath);
|
|
||||||
byte[] rawData = DecryptData(fileData);
|
|
||||||
if (rawData == null || rawData.Length == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return AssetBundle.LoadFromMemory(rawData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
|
|
||||||
/*
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 RawBundle 加载操作(非加密)
|
|
||||||
/// 通用实现,适用于 BuiltinFileSystem 和 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public class DefaultLoadRawBundleOperation : LoadRawBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CheckFilePath,
|
|
||||||
LoadRawBundle,
|
|
||||||
Done
|
|
||||||
}
|
|
||||||
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public DefaultLoadRawBundleOperation(LoadRawBundleOptions options) : base(options) { }
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.CheckFilePath;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.LoadRawBundle)
|
|
||||||
{
|
|
||||||
string filePath = _options.FileLoadPath;
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
{
|
|
||||||
byte[] data = File.ReadAllBytes(filePath);
|
|
||||||
Result = new RawBundle(data);
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Can not found raw bundle file : {filePath}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 RawBundle 加载操作(加密)
|
|
||||||
/// 通用实现,适用于 CacheFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DefaultLoadRawBundleFromMemoryOperation : LoadRawBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CheckFilePath,
|
|
||||||
LoadRawBundle,
|
|
||||||
Done
|
|
||||||
}
|
|
||||||
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
public DefaultLoadRawBundleFromMemoryOperation(LoadRawBundleOptions options) : base(options) { }
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.CheckFilePath;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.LoadRawBundle)
|
|
||||||
{
|
|
||||||
string filePath = _options.FileLoadPath;
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
{
|
|
||||||
byte[] fileData = File.ReadAllBytes(filePath);
|
|
||||||
byte[] rawData = DecryptData(fileData);
|
|
||||||
if (rawData == null || rawData.Length == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.None;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = "Decrypted raw data is null or empty.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Result = new RawBundle(rawData);
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Can not found raw bundle file : {filePath}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文件数据解密
|
|
||||||
/// </summary>
|
|
||||||
protected abstract byte[] DecryptData(byte[] data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
namespace YooAsset
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(非加密)
|
|
||||||
/// 通用实现,适用于 WebRemoteFileSystem 和 WebServerFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public class DefaultLoadWebAssetBundleOperation : LoadWebAssetBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CreateRequest,
|
|
||||||
CheckRequest,
|
|
||||||
TryAgain,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDownloadAssetBundleRequest _downloadAssetBundleRequest;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
private int _requestCount = 0;
|
|
||||||
private float _tryAgainTimer = 0;
|
|
||||||
private int _failedTryAgain;
|
|
||||||
|
|
||||||
public DefaultLoadWebAssetBundleOperation(LoadWebAssetBundleOptions opionts) : base(opionts)
|
|
||||||
{
|
|
||||||
_failedTryAgain = opionts.RetryCount;
|
|
||||||
}
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.CreateRequest;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
if (_steps == ESteps.CreateRequest)
|
|
||||||
{
|
|
||||||
string url = GetRequestURL();
|
|
||||||
var args = new DownloadAssetBundleRequestArgs(url, 0, _options.WatchdogTimeout, _options.DisableUnityWebCache, _options.Bundle.FileHash, _options.Bundle.UnityCRC);
|
|
||||||
_downloadAssetBundleRequest = _options.DownloadBackend.CreateAssetBundleRequest(args);
|
|
||||||
_downloadAssetBundleRequest.SendRequest();
|
|
||||||
_steps = ESteps.CheckRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载结果
|
|
||||||
if (_steps == ESteps.CheckRequest)
|
|
||||||
{
|
|
||||||
Progress = _downloadAssetBundleRequest.DownloadProgress;
|
|
||||||
DownloadedBytes = _downloadAssetBundleRequest.DownloadedBytes;
|
|
||||||
DownloadProgress = _downloadAssetBundleRequest.DownloadProgress;
|
|
||||||
if (_downloadAssetBundleRequest.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_downloadAssetBundleRequest.Status == EDownloadRequestStatus.Succeeded)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
Result = _downloadAssetBundleRequest.Result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_failedTryAgain > 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
YooLogger.Warning($"Failed download : {_downloadAssetBundleRequest.Url} Try again.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = _downloadAssetBundleRequest.Error;
|
|
||||||
YooLogger.Error(Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最终释放请求器
|
|
||||||
_downloadAssetBundleRequest.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新尝试下载
|
|
||||||
if (_steps == ESteps.TryAgain)
|
|
||||||
{
|
|
||||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
|
||||||
if (_tryAgainTimer > 1f)
|
|
||||||
{
|
|
||||||
_tryAgainTimer = 0f;
|
|
||||||
_failedTryAgain--;
|
|
||||||
Progress = 0f;
|
|
||||||
DownloadProgress = 0f;
|
|
||||||
DownloadedBytes = 0;
|
|
||||||
_steps = ESteps.CreateRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取网络请求地址
|
|
||||||
/// </summary>
|
|
||||||
protected string GetRequestURL()
|
|
||||||
{
|
|
||||||
// 轮流返回请求地址
|
|
||||||
_requestCount++;
|
|
||||||
if (_requestCount % 2 == 0)
|
|
||||||
return _options.FallbackURL;
|
|
||||||
else
|
|
||||||
return _options.MainURL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认的 AssetBundle 加载操作(加密)
|
|
||||||
/// 通用实现,适用于 WebRemoteFileSystem 和 WebServerFileSystem
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DefaultLoadWebAssetBundleFromMemoryOperation : LoadWebAssetBundleOperation
|
|
||||||
{
|
|
||||||
private enum ESteps
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
CreateRequest,
|
|
||||||
CheckRequest,
|
|
||||||
TryAgain,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDownloadBytesRequest _downloadBytesRequest;
|
|
||||||
private ESteps _steps = ESteps.None;
|
|
||||||
|
|
||||||
private int _requestCount = 0;
|
|
||||||
private float _tryAgainTimer = 0;
|
|
||||||
private int _failedTryAgain;
|
|
||||||
|
|
||||||
public DefaultLoadWebAssetBundleFromMemoryOperation(LoadWebAssetBundleOptions opionts) : base(opionts)
|
|
||||||
{
|
|
||||||
_failedTryAgain = opionts.RetryCount;
|
|
||||||
}
|
|
||||||
internal override void InternalStart()
|
|
||||||
{
|
|
||||||
_steps = ESteps.CreateRequest;
|
|
||||||
}
|
|
||||||
internal override void InternalUpdate()
|
|
||||||
{
|
|
||||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 创建下载器
|
|
||||||
if (_steps == ESteps.CreateRequest)
|
|
||||||
{
|
|
||||||
string url = GetRequestURL();
|
|
||||||
var args = new DownloadDataRequestArgs(url, 0, _options.WatchdogTimeout);
|
|
||||||
_downloadBytesRequest = _options.DownloadBackend.CreateBytesRequest(args);
|
|
||||||
_downloadBytesRequest.SendRequest();
|
|
||||||
_steps = ESteps.CheckRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测下载结果
|
|
||||||
if (_steps == ESteps.CheckRequest)
|
|
||||||
{
|
|
||||||
Progress = _downloadBytesRequest.DownloadProgress;
|
|
||||||
DownloadProgress = _downloadBytesRequest.DownloadProgress;
|
|
||||||
DownloadedBytes = _downloadBytesRequest.DownloadedBytes;
|
|
||||||
if (_downloadBytesRequest.IsDone == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 检查网络错误
|
|
||||||
if (_downloadBytesRequest.Status == EDownloadRequestStatus.Succeeded)
|
|
||||||
{
|
|
||||||
var rawData = Decryption(_downloadBytesRequest.Result);
|
|
||||||
if (rawData == null || rawData.Length == 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = "AssetBundle raw data is null or empty.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AssetBundle assetBundle = AssetBundle.LoadFromMemory(rawData);
|
|
||||||
if (assetBundle == null)
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = $"Failed load encrypted AssetBundle: {_options.Bundle.BundleName}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Succeeded;
|
|
||||||
Result = assetBundle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_failedTryAgain > 0)
|
|
||||||
{
|
|
||||||
_steps = ESteps.TryAgain;
|
|
||||||
YooLogger.Warning($"Failed download : {_downloadBytesRequest.Url} Try again.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_steps = ESteps.Done;
|
|
||||||
Status = EOperationStatus.Failed;
|
|
||||||
Error = _downloadBytesRequest.Error;
|
|
||||||
YooLogger.Error(Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最终释放请求器
|
|
||||||
_downloadBytesRequest.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新尝试下载
|
|
||||||
if (_steps == ESteps.TryAgain)
|
|
||||||
{
|
|
||||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
|
||||||
if (_tryAgainTimer > 1f)
|
|
||||||
{
|
|
||||||
_tryAgainTimer = 0f;
|
|
||||||
_failedTryAgain--;
|
|
||||||
Progress = 0f;
|
|
||||||
DownloadProgress = 0f;
|
|
||||||
DownloadedBytes = 0;
|
|
||||||
_steps = ESteps.CreateRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文件数据解密
|
|
||||||
/// </summary>
|
|
||||||
protected abstract byte[] Decryption(byte[] data);
|
|
||||||
|
|
||||||
/// 获取网络请求地址
|
|
||||||
/// </summary>
|
|
||||||
protected string GetRequestURL()
|
|
||||||
{
|
|
||||||
// 轮流返回请求地址
|
|
||||||
_requestCount++;
|
|
||||||
if (_requestCount % 2 == 0)
|
|
||||||
return _options.FallbackURL;
|
|
||||||
else
|
|
||||||
return _options.MainURL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -31,12 +31,12 @@ namespace YooAsset
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载Bundle文件
|
/// 下载Bundle文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options);
|
FSDownloadFileOperation DownloadFileAsync(FSDownloadFileOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载Bundle文件
|
/// 加载Bundle文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options);
|
FSLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class LoadWebPackageManifestOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestFileData,
|
||||||
|
VerifyFileData,
|
||||||
|
LoadManifest,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly LoadWebPackageManifestOptions _options;
|
||||||
|
private IDownloadBytesRequest _webDataRequestOp;
|
||||||
|
private DeserializeManifestOperation _deserializer;
|
||||||
|
private int _requestCount = 0;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹清单
|
||||||
|
/// </summary>
|
||||||
|
public PackageManifest Manifest { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
internal LoadWebPackageManifestOperation(LoadWebPackageManifestOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
internal override void InternalStart()
|
||||||
|
{
|
||||||
|
_requestCount = DownloadFailureCounter.GetFailureCount(_options.PackageName, nameof(LoadWebPackageManifestOperation));
|
||||||
|
_steps = ESteps.RequestFileData;
|
||||||
|
}
|
||||||
|
internal override void InternalUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestFileData)
|
||||||
|
{
|
||||||
|
if (_webDataRequestOp == null)
|
||||||
|
{
|
||||||
|
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_options.PackageName, _options.PackageVersion);
|
||||||
|
string url = GetRequestURL(fileName);
|
||||||
|
var args = new DownloadDataRequestArgs(url, _options.Timeout, 0);
|
||||||
|
_webDataRequestOp = _options.DownloadBackend.CreateBytesRequest(args);
|
||||||
|
_webDataRequestOp.SendRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress = _webDataRequestOp.DownloadProgress;
|
||||||
|
if (_webDataRequestOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_webDataRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
||||||
|
{
|
||||||
|
_steps = ESteps.VerifyFileData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _webDataRequestOp.Error;
|
||||||
|
DownloadFailureCounter.RecordFailure(_options.PackageName, nameof(LoadWebPackageManifestOperation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.VerifyFileData)
|
||||||
|
{
|
||||||
|
if (PackageManifestTools.VerifyManifestData(_webDataRequestOp.Result, _options.PackageHash))
|
||||||
|
{
|
||||||
|
_steps = ESteps.LoadManifest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = "Failed to verify web package manifest file.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_steps == ESteps.LoadManifest)
|
||||||
|
{
|
||||||
|
if (_deserializer == null)
|
||||||
|
{
|
||||||
|
_deserializer = new DeserializeManifestOperation(_options.ManifestDecryptor, _webDataRequestOp.Result);
|
||||||
|
_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 void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_webDataRequestOp != null)
|
||||||
|
{
|
||||||
|
_webDataRequestOp.Dispose();
|
||||||
|
_webDataRequestOp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override string InternalGetDescription()
|
||||||
|
{
|
||||||
|
return $"PackageVersion : {_options.PackageVersion} PackageHash : {_options.PackageHash}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRequestURL(string fileName)
|
||||||
|
{
|
||||||
|
// 轮流返回请求地址
|
||||||
|
if (_requestCount % 2 == 0)
|
||||||
|
return _options.RemoteServices.GetRemoteMainURL(fileName);
|
||||||
|
else
|
||||||
|
return _options.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal struct LoadWebPackageManifestOptions
|
||||||
|
{
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
public string PackageVersion { get; set; }
|
||||||
|
public string PackageHash { get; set; }
|
||||||
|
public int Timeout { get; set; }
|
||||||
|
|
||||||
|
public IRemoteServices RemoteServices { get; set; }
|
||||||
|
public IManifestDecryptor ManifestDecryptor { get; set; }
|
||||||
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 067ac2067f265624bac214127575d7d5
|
guid: cbabf286b35608d419c6b1e56499d2ca
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class RequestWebPackageHashOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestPackageHash,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly RequestWebPackageHashOptions _options;
|
||||||
|
private IDownloadTextRequest _webTextRequestOp;
|
||||||
|
private int _requestCount = 0;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹哈希值
|
||||||
|
/// </summary>
|
||||||
|
public string PackageHash { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
public RequestWebPackageHashOperation(RequestWebPackageHashOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
internal override void InternalStart()
|
||||||
|
{
|
||||||
|
_requestCount = DownloadFailureCounter.GetFailureCount(_options.PackageName, nameof(RequestWebPackageHashOperation));
|
||||||
|
_steps = ESteps.RequestPackageHash;
|
||||||
|
}
|
||||||
|
internal override void InternalUpdate()
|
||||||
|
{
|
||||||
|
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_steps == ESteps.RequestPackageHash)
|
||||||
|
{
|
||||||
|
if (_webTextRequestOp == null)
|
||||||
|
{
|
||||||
|
string fileName = YooAssetSettingsData.GetPackageHashFileName(_options.PackageName, _options.PackageVersion);
|
||||||
|
string url = GetRequestURL(fileName);
|
||||||
|
var args = new DownloadDataRequestArgs(url, _options.Timeout, 0);
|
||||||
|
_webTextRequestOp = _options.DownloadBackend.CreateTextRequest(args);
|
||||||
|
_webTextRequestOp.SendRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress = _webTextRequestOp.DownloadProgress;
|
||||||
|
if (_webTextRequestOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
||||||
|
{
|
||||||
|
PackageHash = _webTextRequestOp.Result;
|
||||||
|
if (string.IsNullOrEmpty(PackageHash))
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Web package hash file content is empty.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Succeeded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = _webTextRequestOp.Error;
|
||||||
|
DownloadFailureCounter.RecordFailure(_options.PackageName, nameof(RequestWebPackageHashOperation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_webTextRequestOp != null)
|
||||||
|
{
|
||||||
|
_webTextRequestOp.Dispose();
|
||||||
|
_webTextRequestOp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRequestURL(string fileName)
|
||||||
|
{
|
||||||
|
// 轮流返回请求地址
|
||||||
|
if (_requestCount % 2 == 0)
|
||||||
|
return _options.RemoteServices.GetRemoteMainURL(fileName);
|
||||||
|
else
|
||||||
|
return _options.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal struct RequestWebPackageHashOptions
|
||||||
|
{
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
public string PackageVersion { get; set; }
|
||||||
|
public int Timeout { get; set; }
|
||||||
|
|
||||||
|
public IRemoteServices RemoteServices { get; set; }
|
||||||
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: cc25b8eb3bf83474f942e36bf7b3210d
|
guid: 4ba57dfeb7916fd46bb58b673fc08ef4
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal class RequestWebPackageVersionOperation : AsyncOperationBase
|
||||||
|
{
|
||||||
|
private enum ESteps
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
RequestPackageVersion,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly RequestWebPackageVersionOptions _options;
|
||||||
|
private IDownloadTextRequest _webTextRequestOp;
|
||||||
|
private int _requestCount = 0;
|
||||||
|
private ESteps _steps = ESteps.None;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包裹版本
|
||||||
|
/// </summary>
|
||||||
|
public string PackageVersion { private set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
public RequestWebPackageVersionOperation(RequestWebPackageVersionOptions options)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
}
|
||||||
|
internal override void InternalStart()
|
||||||
|
{
|
||||||
|
_requestCount = DownloadFailureCounter.GetFailureCount(_options.PackageName, nameof(RequestWebPackageVersionOperation));
|
||||||
|
_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(_options.PackageName);
|
||||||
|
string url = GetRequestURL(fileName);
|
||||||
|
var args = new DownloadDataRequestArgs(url, _options.Timeout, 0);
|
||||||
|
_webTextRequestOp = _options.DownloadBackend.CreateTextRequest(args);
|
||||||
|
_webTextRequestOp.SendRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress = _webTextRequestOp.DownloadProgress;
|
||||||
|
if (_webTextRequestOp.IsDone == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_webTextRequestOp.Status == EDownloadRequestStatus.Succeeded)
|
||||||
|
{
|
||||||
|
PackageVersion = _webTextRequestOp.Result;
|
||||||
|
if (string.IsNullOrEmpty(PackageVersion))
|
||||||
|
{
|
||||||
|
_steps = ESteps.Done;
|
||||||
|
Status = EOperationStatus.Failed;
|
||||||
|
Error = $"Web 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(_options.PackageName, nameof(RequestWebPackageVersionOperation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal override void InternalDispose()
|
||||||
|
{
|
||||||
|
if (_webTextRequestOp != null)
|
||||||
|
{
|
||||||
|
_webTextRequestOp.Dispose();
|
||||||
|
_webTextRequestOp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRequestURL(string fileName)
|
||||||
|
{
|
||||||
|
string url;
|
||||||
|
|
||||||
|
// 轮流返回请求地址
|
||||||
|
if (_requestCount % 2 == 0)
|
||||||
|
url = _options.RemoteServices.GetRemoteMainURL(fileName);
|
||||||
|
else
|
||||||
|
url = _options.RemoteServices.GetRemoteFallbackURL(fileName);
|
||||||
|
|
||||||
|
// 在URL末尾添加时间戳
|
||||||
|
if (_options.AppendTimeTicks)
|
||||||
|
return $"{url}?{System.DateTime.UtcNow.Ticks}";
|
||||||
|
else
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace YooAsset
|
||||||
|
{
|
||||||
|
internal struct RequestWebPackageVersionOptions
|
||||||
|
{
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
public bool AppendTimeTicks { get; set; }
|
||||||
|
public int Timeout { get; set; }
|
||||||
|
|
||||||
|
public IRemoteServices RemoteServices { get; set; }
|
||||||
|
public IDownloadBackend DownloadBackend { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 05b4aa37709184a408090202f98b93d3
|
guid: 1109ea54301470d4283f1b9b88d176ca
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
namespace YooAsset
|
namespace YooAsset
|
||||||
{
|
{
|
||||||
internal readonly struct DownloadFileOptions
|
internal readonly struct FSDownloadFileOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 资源包对象
|
/// 资源包对象
|
||||||
@@ -18,13 +18,13 @@ namespace YooAsset
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly string ImportFilePath;
|
public readonly string ImportFilePath;
|
||||||
|
|
||||||
public DownloadFileOptions(PackageBundle bundle, int retryCount)
|
public FSDownloadFileOptions(PackageBundle bundle, int retryCount)
|
||||||
{
|
{
|
||||||
Bundle = bundle;
|
Bundle = bundle;
|
||||||
RetryCount = retryCount;
|
RetryCount = retryCount;
|
||||||
ImportFilePath = null;
|
ImportFilePath = null;
|
||||||
}
|
}
|
||||||
public DownloadFileOptions(PackageBundle bundle, int retryCount, string importFilePath)
|
public FSDownloadFileOptions(PackageBundle bundle, int retryCount, string importFilePath)
|
||||||
{
|
{
|
||||||
Bundle = bundle;
|
Bundle = bundle;
|
||||||
RetryCount = retryCount;
|
RetryCount = retryCount;
|
||||||
|
|||||||
@@ -137,12 +137,12 @@ namespace YooAsset
|
|||||||
var operation = new BFSClearCacheOperation(this, options);
|
var operation = new BFSClearCacheOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FSDownloadFileOperation DownloadFileAsync(DownloadFileOptions options)
|
public virtual FSDownloadFileOperation DownloadFileAsync(FSDownloadFileOptions options)
|
||||||
{
|
{
|
||||||
var operation = new BFSDownloadFileOperation(this, options);
|
var operation = new BFSDownloadFileOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
}
|
}
|
||||||
public virtual FSLoadBundleOperation LoadBundleAsync(LoadBundleOptions options)
|
public virtual FSLoadBundleOperation LoadBundleAsync(FCLoadBundleOptions options)
|
||||||
{
|
{
|
||||||
var operation = new BFSLoadBundleOperation(this, options);
|
var operation = new BFSLoadBundleOperation(this, options);
|
||||||
return operation;
|
return operation;
|
||||||
@@ -235,21 +235,21 @@ namespace YooAsset
|
|||||||
else
|
else
|
||||||
_packageRoot = packageRoot;
|
_packageRoot = packageRoot;
|
||||||
|
|
||||||
// 创建默认的下载后台接口
|
// 设置根目录
|
||||||
if (DownloadBackend == null)
|
|
||||||
DownloadBackend = new UnityWebRequestBackend(WebRequestCreator);
|
|
||||||
|
|
||||||
// 创建解压缓存系统
|
|
||||||
string unpackRoot;
|
string unpackRoot;
|
||||||
if (string.IsNullOrEmpty(UnpackFileSystemRoot))
|
if (string.IsNullOrEmpty(UnpackFileSystemRoot))
|
||||||
unpackRoot = GetDefaultUnpackCacheRoot(packageName);
|
unpackRoot = GetDefaultUnpackPathRoot(packageName);
|
||||||
else
|
else
|
||||||
unpackRoot = UnpackFileSystemRoot;
|
unpackRoot = UnpackFileSystemRoot;
|
||||||
_unpackManifestFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackManifestFilesFolderName);
|
_unpackManifestFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackManifestFilesFolderName);
|
||||||
_unpackBundleFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackBundleFilesFolderName);
|
_unpackBundleFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackBundleFilesFolderName);
|
||||||
_unpackTempFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackTempFilesFolderName);
|
_unpackTempFilesRoot = PathUtility.Combine(unpackRoot, BuiltinFileSystemDefine.UnpackTempFilesFolderName);
|
||||||
|
|
||||||
// 创建内置缓存对象
|
// 创建默认的下载后台接口
|
||||||
|
if (DownloadBackend == null)
|
||||||
|
DownloadBackend = new UnityWebRequestBackend(WebRequestCreator);
|
||||||
|
|
||||||
|
// 创建内置文件缓存系统
|
||||||
{
|
{
|
||||||
var cacheConfig = new BuiltinFileCache.CacheConfig();
|
var cacheConfig = new BuiltinFileCache.CacheConfig();
|
||||||
cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor;
|
cacheConfig.AssetBundleDecryptor = AssetBundleDecryptor;
|
||||||
@@ -258,7 +258,7 @@ namespace YooAsset
|
|||||||
BuiltinFileCache = new BuiltinFileCache(packageName, _packageRoot, cacheConfig);
|
BuiltinFileCache = new BuiltinFileCache(packageName, _packageRoot, cacheConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建沙盒缓存对象
|
// 创建沙盒文件缓存系统
|
||||||
{
|
{
|
||||||
var cacheConfig = new SandboxFileCache.CacheConfig();
|
var cacheConfig = new SandboxFileCache.CacheConfig();
|
||||||
cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency;
|
cacheConfig.FileVerifyMaxConcurrency = FileVerifyMaxConcurrency;
|
||||||
@@ -377,7 +377,7 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除所有缓存的资源文件
|
/// 删除所有解压的资源文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void DeleteAllBundleFiles()
|
public void DeleteAllBundleFiles()
|
||||||
{
|
{
|
||||||
@@ -388,9 +388,9 @@ namespace YooAsset
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取默认的解压缓存根目录
|
/// 获取默认的解压根目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string GetDefaultUnpackCacheRoot(string packageName)
|
public string GetDefaultUnpackPathRoot(string packageName)
|
||||||
{
|
{
|
||||||
string rootDirectory = YooAssetSettingsData.GetYooDefaultCacheRoot();
|
string rootDirectory = YooAssetSettingsData.GetYooDefaultCacheRoot();
|
||||||
return PathUtility.Combine(rootDirectory, packageName);
|
return PathUtility.Combine(rootDirectory, packageName);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user