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