Update CacheSystem

优化缓存系统代码结构
pull/36/head
hevinci 2022-08-15 11:55:13 +08:00
parent aba68f859f
commit fbbf762e70
26 changed files with 306 additions and 446 deletions

View File

@ -273,7 +273,7 @@ namespace YooAsset
private static AssetBundleLoaderBase CreateAssetBundleLoaderInternal(BundleInfo bundleInfo) private static AssetBundleLoaderBase CreateAssetBundleLoaderInternal(BundleInfo bundleInfo)
{ {
// 如果加载器已经存在 // 如果加载器已经存在
AssetBundleLoaderBase loader = TryGetAssetBundleLoader(bundleInfo.BundleName); AssetBundleLoaderBase loader = TryGetAssetBundleLoader(bundleInfo.Bundle.BundleName);
if (loader != null) if (loader != null)
return loader; return loader;
@ -293,7 +293,7 @@ namespace YooAsset
for (int i = 0; i < _loaders.Count; i++) for (int i = 0; i < _loaders.Count; i++)
{ {
AssetBundleLoaderBase temp = _loaders[i]; AssetBundleLoaderBase temp = _loaders[i];
if (temp.MainBundleInfo.BundleName.Equals(bundleName)) if (temp.MainBundleInfo.Bundle.BundleName.Equals(bundleName))
{ {
loader = temp; loader = temp;
break; break;

View File

@ -40,29 +40,20 @@ namespace YooAsset
if (_steps == ESteps.None) if (_steps == ESteps.None)
{ {
if (MainBundleInfo.IsInvalid)
{
_steps = ESteps.Done;
Status = EStatus.Failed;
LastError = $"The bundle info is invalid : {MainBundleInfo.BundleName}";
YooLogger.Error(LastError);
return;
}
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
{ {
_steps = ESteps.Download; _steps = ESteps.Download;
_fileLoadPath = MainBundleInfo.GetCacheLoadPath(); _fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
} }
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
_steps = ESteps.LoadFile; _steps = ESteps.LoadFile;
_fileLoadPath = MainBundleInfo.GetStreamingLoadPath(); _fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
} }
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
_steps = ESteps.LoadFile; _steps = ESteps.LoadFile;
_fileLoadPath = MainBundleInfo.GetCacheLoadPath(); _fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
} }
else else
{ {
@ -112,15 +103,14 @@ namespace YooAsset
#endif #endif
// Load assetBundle file // Load assetBundle file
if (MainBundleInfo.IsEncrypted) if (MainBundleInfo.Bundle.IsEncrypted)
{ {
if (AssetSystem.DecryptionServices == null) if (AssetSystem.DecryptionServices == null)
throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.BundleName}"); throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.Bundle.BundleName}");
DecryptionFileInfo fileInfo = new DecryptionFileInfo(); DecryptionFileInfo fileInfo = new DecryptionFileInfo();
fileInfo.BundleName = MainBundleInfo.BundleName; fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
fileInfo.FileHash = MainBundleInfo.FileHash; fileInfo.FileHash = MainBundleInfo.Bundle.FileHash;
fileInfo.FileCRC = MainBundleInfo.FileCRC;
ulong offset = AssetSystem.DecryptionServices.GetFileOffset(fileInfo); ulong offset = AssetSystem.DecryptionServices.GetFileOffset(fileInfo);
if (_isWaitForAsyncComplete) if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset); CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset);
@ -161,15 +151,15 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EStatus.Failed; Status = EStatus.Failed;
LastError = $"Failed to load assetBundle : {MainBundleInfo.BundleName}"; LastError = $"Failed to load assetBundle : {MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError); YooLogger.Error(LastError);
// 注意当缓存文件的校验等级为Low的时候并不能保证缓存文件的完整性。 // 注意当缓存文件的校验等级为Low的时候并不能保证缓存文件的完整性。
// 在AssetBundle文件加载失败的情况下我们需要重新验证文件的完整性 // 在AssetBundle文件加载失败的情况下我们需要重新验证文件的完整性
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
string cacheLoadPath = MainBundleInfo.GetCacheLoadPath(); string cacheLoadPath = MainBundleInfo.Bundle.CachedFilePath;
if (CacheSystem.CheckContentIntegrity(EVerifyLevel.High, cacheLoadPath, MainBundleInfo.FileSize, MainBundleInfo.FileCRC) == false) if (CacheSystem.VerifyBundle(MainBundleInfo.Bundle, EVerifyLevel.High) == false)
{ {
if (File.Exists(cacheLoadPath)) if (File.Exists(cacheLoadPath))
{ {
@ -205,7 +195,7 @@ namespace YooAsset
if (_isShowWaitForAsyncError == false) if (_isShowWaitForAsyncError == false)
{ {
_isShowWaitForAsyncError = true; _isShowWaitForAsyncError = true;
YooLogger.Error($"WaitForAsyncComplete failed ! Try load bundle : {MainBundleInfo.BundleName} from remote with sync load method !"); YooLogger.Error($"WaitForAsyncComplete failed ! Try load bundle : {MainBundleInfo.Bundle.BundleName} from remote with sync load method !");
} }
break; break;
} }

View File

@ -91,9 +91,9 @@ namespace YooAsset
if (forceDestroy == false) if (forceDestroy == false)
{ {
if (RefCount > 0) if (RefCount > 0)
throw new Exception($"Bundle file loader ref is not zero : {MainBundleInfo.BundleName}"); throw new Exception($"Bundle file loader ref is not zero : {MainBundleInfo.Bundle.BundleName}");
if (IsDone() == false) if (IsDone() == false)
throw new Exception($"Bundle file loader is not done : {MainBundleInfo.BundleName}"); throw new Exception($"Bundle file loader is not done : {MainBundleInfo.Bundle.BundleName}");
} }
if (CacheBundle != null) if (CacheBundle != null)

View File

@ -38,19 +38,10 @@ namespace YooAsset
if (_steps == ESteps.None) if (_steps == ESteps.None)
{ {
if (MainBundleInfo.IsInvalid)
{
_steps = ESteps.Done;
Status = EStatus.Failed;
LastError = $"The bundle info is invalid : {MainBundleInfo.BundleName}";
YooLogger.Error(LastError);
return;
}
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
_steps = ESteps.LoadFile; _steps = ESteps.LoadFile;
_webURL = MainBundleInfo.GetStreamingLoadPath(); _webURL = MainBundleInfo.Bundle.StreamingFilePath;
} }
else else
{ {
@ -61,7 +52,7 @@ namespace YooAsset
// 1. 从服务器或缓存中获取AssetBundle文件 // 1. 从服务器或缓存中获取AssetBundle文件
if (_steps == ESteps.LoadFile) if (_steps == ESteps.LoadFile)
{ {
_webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_webURL, Hash128.Parse(MainBundleInfo.FileHash)); _webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_webURL, Hash128.Parse(MainBundleInfo.Bundle.FileHash));
_webRequest.SendWebRequest(); _webRequest.SendWebRequest();
_steps = ESteps.CheckFile; _steps = ESteps.CheckFile;
} }
@ -89,7 +80,7 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EStatus.Failed; Status = EStatus.Failed;
LastError = $"AssetBundle file is invalid : {MainBundleInfo.BundleName}"; LastError = $"AssetBundle file is invalid : {MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError); YooLogger.Error(LastError);
} }
else else

View File

@ -102,7 +102,7 @@ namespace YooAsset
foreach (var loader in _dependBundles) foreach (var loader in _dependBundles)
{ {
var bundleInfo = new DebugBundleInfo(); var bundleInfo = new DebugBundleInfo();
bundleInfo.BundleName = loader.MainBundleInfo.BundleName; bundleInfo.BundleName = loader.MainBundleInfo.Bundle.BundleName;
bundleInfo.RefCount = loader.RefCount; bundleInfo.RefCount = loader.RefCount;
bundleInfo.Status = (int)loader.Status; bundleInfo.Status = (int)loader.Status;
output.Add(bundleInfo); output.Add(bundleInfo);

View File

@ -171,14 +171,14 @@ namespace YooAsset
{ {
None, None,
Prepare, Prepare,
DownloadFromApk, DownloadBuildinFile,
CheckDownloadFromApk, CheckDownload,
CheckAndCopyFile, CheckAndCopyFile,
Done, Done,
} }
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private UnityWebFileRequester _fileRequester; private DownloaderBase _downloader;
public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath) public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{ {
@ -199,14 +199,15 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Bundle info is invalid : {_bundleInfo.BundleName}"; Error = $"Bundle info is invalid : {_bundleInfo.Bundle.BundleName}";
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
if (CacheSystem.ContainsVerifyFile(_bundleInfo.LoadBundle)) _steps = ESteps.DownloadBuildinFile;
_steps = ESteps.CheckAndCopyFile; }
else else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
_steps = ESteps.DownloadFromApk; {
_steps = ESteps.CheckAndCopyFile;
} }
else else
{ {
@ -214,43 +215,32 @@ namespace YooAsset
} }
} }
// 2. 从APK拷贝文件 // 2. 下载文件
if (_steps == ESteps.DownloadFromApk) if (_steps == ESteps.DownloadBuildinFile)
{ {
string downloadURL = PathHelper.ConvertToWWWPath(_bundleInfo.GetStreamingLoadPath()); int failedTryAgain = int.MaxValue;
_fileRequester = new UnityWebFileRequester(); var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
_fileRequester.SendRequest(downloadURL, GetCachePath()); _downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownloadFromApk; _steps = ESteps.CheckDownload;
} }
// 3. 检测APK拷贝文件结果 // 3. 检测下载结果
if (_steps == ESteps.CheckDownloadFromApk) if (_steps == ESteps.CheckDownload)
{ {
Progress = _fileRequester.Progress(); Progress = _downloader.DownloadProgress;
if (_fileRequester.IsDone() == false) if (_downloader.IsDone() == false)
return; return;
if (_fileRequester.HasError()) if (_downloader.HasError())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _fileRequester.GetError(); Error = _downloader.GetLastError();
} }
else else
{ {
if (CacheSystem.CheckContentIntegrity(GetCachePath(), _bundleInfo.FileSize, _bundleInfo.FileCRC)) _steps = ESteps.CheckAndCopyFile;
{
CacheSystem.CacheVerifyFile(_bundleInfo.LoadBundle);
_steps = ESteps.CheckAndCopyFile;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "File content verify failed !";
}
} }
_fileRequester.Dispose();
} }
// 4. 检测并拷贝原生文件 // 4. 检测并拷贝原生文件
@ -267,7 +257,7 @@ namespace YooAsset
// 如果原生文件已经存在,则验证其完整性 // 如果原生文件已经存在,则验证其完整性
if (File.Exists(CopyPath)) if (File.Exists(CopyPath))
{ {
bool result = CacheSystem.CheckContentIntegrity(CopyPath, _bundleInfo.FileSize, _bundleInfo.FileCRC); bool result = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
if (result) if (result)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
@ -303,7 +293,7 @@ namespace YooAsset
{ {
if (_bundleInfo == null) if (_bundleInfo == null)
return string.Empty; return string.Empty;
return _bundleInfo.GetCacheLoadPath(); return _bundleInfo.Bundle.CachedFilePath;
} }
} }
@ -316,17 +306,15 @@ namespace YooAsset
{ {
None, None,
Prepare, Prepare,
DownloadFromWeb, DownloadWebFile,
CheckDownloadFromWeb, DownloadBuildinFile,
DownloadFromApk, CheckDownload,
CheckDownloadFromApk,
CheckAndCopyFile, CheckAndCopyFile,
Done, Done,
} }
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private DownloaderBase _downloader; private DownloaderBase _downloader;
private UnityWebFileRequester _fileRequester;
internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath) internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{ {
@ -347,18 +335,15 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Bundle info is invalid : {_bundleInfo.BundleName}"; Error = $"Bundle info is invalid : {_bundleInfo.Bundle.BundleName}";
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
{ {
_steps = ESteps.DownloadFromWeb; _steps = ESteps.DownloadWebFile;
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
if (CacheSystem.ContainsVerifyFile(_bundleInfo.LoadBundle)) _steps = ESteps.DownloadBuildinFile;
_steps = ESteps.CheckAndCopyFile;
else
_steps = ESteps.DownloadFromApk;
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
@ -370,16 +355,25 @@ namespace YooAsset
} }
} }
// 2. 从服务器下载 // 2. 下载远端文件
if (_steps == ESteps.DownloadFromWeb) if (_steps == ESteps.DownloadWebFile)
{ {
int failedTryAgain = int.MaxValue; int failedTryAgain = int.MaxValue;
_downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain); _downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownloadFromWeb; _steps = ESteps.CheckDownload;
} }
// 3. 检测服务器下载结果 // 3. 下载内置文件
if (_steps == ESteps.CheckDownloadFromWeb) if (_steps == ESteps.DownloadBuildinFile)
{
int failedTryAgain = int.MaxValue;
var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload;
}
// 4. 检测下载结果
if (_steps == ESteps.CheckDownload)
{ {
Progress = _downloader.DownloadProgress; Progress = _downloader.DownloadProgress;
if (_downloader.IsDone() == false) if (_downloader.IsDone() == false)
@ -397,46 +391,7 @@ namespace YooAsset
} }
} }
// 4. 从APK拷贝文件 // 5. 检测并拷贝原生文件
if (_steps == ESteps.DownloadFromApk)
{
string downloadURL = PathHelper.ConvertToWWWPath(_bundleInfo.GetStreamingLoadPath());
_fileRequester = new UnityWebFileRequester();
_fileRequester.SendRequest(downloadURL, GetCachePath());
_steps = ESteps.CheckDownloadFromApk;
}
// 5. 检测APK拷贝文件结果
if (_steps == ESteps.CheckDownloadFromApk)
{
Progress = _fileRequester.Progress();
if (_fileRequester.IsDone() == false)
return;
if (_fileRequester.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _fileRequester.GetError();
}
else
{
if (CacheSystem.CheckContentIntegrity(GetCachePath(), _bundleInfo.FileSize, _bundleInfo.FileCRC))
{
CacheSystem.CacheVerifyFile(_bundleInfo.LoadBundle);
_steps = ESteps.CheckAndCopyFile;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "File content verify failed !";
}
}
_fileRequester.Dispose();
}
// 6. 检测并拷贝原生文件
if (_steps == ESteps.CheckAndCopyFile) if (_steps == ESteps.CheckAndCopyFile)
{ {
// 如果不需要保存文件 // 如果不需要保存文件
@ -450,7 +405,7 @@ namespace YooAsset
// 如果原生文件已经存在,则验证其完整性 // 如果原生文件已经存在,则验证其完整性
if (File.Exists(CopyPath)) if (File.Exists(CopyPath))
{ {
bool result = CacheSystem.CheckContentIntegrity(CopyPath, _bundleInfo.FileSize, _bundleInfo.FileCRC); bool result = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
if (result) if (result)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
@ -486,7 +441,7 @@ namespace YooAsset
{ {
if (_bundleInfo == null) if (_bundleInfo == null)
return string.Empty; return string.Empty;
return _bundleInfo.GetCacheLoadPath(); return _bundleInfo.Bundle.CachedFilePath;
} }
} }
} }

View File

@ -65,7 +65,7 @@ namespace YooAsset
if (OwnerBundle.IsDestroyed) if (OwnerBundle.IsDestroyed)
throw new System.Exception("Should never get here !"); throw new System.Exception("Should never get here !");
Status = EStatus.Fail; Status = EStatus.Fail;
LastError = $"The bundle {OwnerBundle.MainBundleInfo.BundleName} has been destroyed by unity bugs !"; LastError = $"The bundle {OwnerBundle.MainBundleInfo.Bundle.BundleName} has been destroyed by unity bugs !";
InvokeCompletion(); InvokeCompletion();
return; return;
} }
@ -116,9 +116,9 @@ namespace YooAsset
if (Status == EStatus.Fail) if (Status == EStatus.Fail)
{ {
if (MainAssetInfo.AssetType == null) if (MainAssetInfo.AssetType == null)
LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
else else
LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType} AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType} AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError); YooLogger.Error(LastError);
} }
InvokeCompletion(); InvokeCompletion();

View File

@ -41,7 +41,7 @@ namespace YooAsset
internal void GetBundleDebugInfos(List<DebugBundleInfo> output) internal void GetBundleDebugInfos(List<DebugBundleInfo> output)
{ {
var bundleInfo = new DebugBundleInfo(); var bundleInfo = new DebugBundleInfo();
bundleInfo.BundleName = OwnerBundle.MainBundleInfo.BundleName; bundleInfo.BundleName = OwnerBundle.MainBundleInfo.Bundle.BundleName;
bundleInfo.RefCount = OwnerBundle.RefCount; bundleInfo.RefCount = OwnerBundle.RefCount;
bundleInfo.Status = (int)OwnerBundle.Status; bundleInfo.Status = (int)OwnerBundle.Status;
output.Add(bundleInfo); output.Add(bundleInfo);

View File

@ -106,9 +106,9 @@ namespace YooAsset
if (Status == EStatus.Fail) if (Status == EStatus.Fail)
{ {
if (MainAssetInfo.AssetType == null) if (MainAssetInfo.AssetType == null)
LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
else else
LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType} AssetBundle : {OwnerBundle.MainBundleInfo.BundleName}"; LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : {MainAssetInfo.AssetType} AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError); YooLogger.Error(LastError);
} }
InvokeCompletion(); InvokeCompletion();

View File

@ -2,71 +2,46 @@
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine;
namespace YooAsset namespace YooAsset
{ {
internal static class CacheSystem internal static class CacheSystem
{ {
private readonly static HashSet<PatchBundle> _cacheBundles = new HashSet<PatchBundle>(); private readonly static Dictionary<string, PatchBundle> _cachedDic = new Dictionary<string, PatchBundle>(1000);
private readonly static Dictionary<string, string> _cachedHashList = new Dictionary<string, string>(1000);
private static EVerifyLevel _verifyLevel = EVerifyLevel.High;
public static void Initialize(EVerifyLevel verifyLevel) /// <summary>
/// 初始化时的验证级别
/// </summary>
public static EVerifyLevel InitVerifyLevel { private set; get; }
public static void Initialize(EVerifyLevel initVerifyLevel)
{ {
_verifyLevel = verifyLevel; InitVerifyLevel = initVerifyLevel;
} }
public static void DestroyAll() public static void DestroyAll()
{ {
_cacheBundles.Clear(); _cachedDic.Clear();
} }
public static void WriteInfoFileForCachedFile()
{
}
public static void ReadInfoFileForCachedFile()
{
}
public static void GetCachingDiskSpaceUsed()
{
}
public static void GetCachingDiskSpaceFree()
{
}
public static bool IsCached(PatchBundle patchBundle)
{
return false;
}
public static void ClearCache()
{
}
/// <summary> /// <summary>
/// 查询是否为验证文件 /// 查询是否为验证文件
/// 注意:被收录的文件完整性是绝对有效的 /// 注意:被收录的文件完整性是绝对有效的
/// </summary> /// </summary>
public static bool ContainsVerifyFile(PatchBundle patchBundle) public static bool IsCached(PatchBundle patchBundle)
{ {
string fileHash = patchBundle.FileHash; string fileHash = patchBundle.FileHash;
if (_cachedHashList.ContainsKey(fileHash)) if (_cachedDic.ContainsKey(fileHash))
{ {
string fileName = _cachedHashList[fileHash]; string filePath = patchBundle.CachedFilePath;
string filePath = SandboxHelper.MakeCacheFilePath(fileName);
if (File.Exists(filePath)) if (File.Exists(filePath))
{ {
return true; return true;
} }
else else
{ {
_cachedHashList.Remove(fileHash); _cachedDic.Remove(fileHash);
YooLogger.Error($"Cache file is missing : {fileName}"); YooLogger.Error($"Cache file is missing : {filePath}");
return false; return false;
} }
} }
@ -77,31 +52,47 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 缓存验证过的文件 /// 缓存补丁包文件
/// </summary> /// </summary>
public static void CacheVerifyFile(PatchBundle patchBundle) public static void CacheBundle(PatchBundle patchBundle)
{ {
string fileHash = patchBundle.FileHash; string fileHash = patchBundle.FileHash;
string fileName = patchBundle.FileName; if (_cachedDic.ContainsKey(fileHash) == false)
if (_cachedHashList.ContainsKey(fileHash) == false)
{ {
YooLogger.Log($"Cache verify file : {fileName}"); string filePath = patchBundle.CachedFilePath;
_cachedHashList.Add(fileHash, fileName); YooLogger.Log($"Cache verify file : {filePath}");
_cachedDic.Add(fileHash, patchBundle);
}
}
/// <summary>
/// 验证补丁包文件
/// </summary>
public static bool VerifyBundle(PatchBundle patchBundle, EVerifyLevel verifyLevel)
{
return VerifyContentInternal(patchBundle.CachedFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
}
/// <summary>
/// 验证并缓存补丁包文件
/// </summary>
public static bool VerifyAndCacheBundle(PatchBundle patchBundle, EVerifyLevel verifyLevel)
{
if (VerifyContentInternal(patchBundle.CachedFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel))
{
CacheBundle(patchBundle);
return true;
}
else
{
return false;
} }
} }
/// <summary> /// <summary>
/// 验证文件完整性 /// 验证文件完整性
/// </summary> /// </summary>
public static bool CheckContentIntegrity(string filePath, long fileSize, string fileCRC) public static bool VerifyContentInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
{
return CheckContentIntegrity(_verifyLevel, filePath, fileSize, fileCRC);
}
/// <summary>
/// 验证文件完整性
/// </summary>
public static bool CheckContentIntegrity(EVerifyLevel verifyLevel, string filePath, long fileSize, string fileCRC)
{ {
try try
{ {

View File

@ -48,7 +48,7 @@ namespace YooAsset
foreach (var patchBundle in localPatchManifest.BundleList) foreach (var patchBundle in localPatchManifest.BundleList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -62,7 +62,7 @@ namespace YooAsset
// 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性 // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
if (weaklyUpdate) if (weaklyUpdate)
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); string filePath = patchBundle.CachedFilePath;
if (File.Exists(filePath)) if (File.Exists(filePath))
_waitingList.Add(patchBundle); _waitingList.Add(patchBundle);
else else
@ -70,7 +70,7 @@ namespace YooAsset
} }
else else
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); string filePath = patchBundle.CachedFilePath;
if (File.Exists(filePath)) if (File.Exists(filePath))
_waitingList.Add(patchBundle); _waitingList.Add(patchBundle);
} }
@ -124,14 +124,14 @@ namespace YooAsset
private bool VerifyFile(PatchBundle patchBundle) private bool VerifyFile(PatchBundle patchBundle)
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); string filePath = patchBundle.CachedFilePath;
ThreadInfo info = new ThreadInfo(filePath, patchBundle); ThreadInfo info = new ThreadInfo(filePath, patchBundle);
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), info); return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), info);
} }
private void VerifyInThread(object infoObj) private void VerifyInThread(object infoObj)
{ {
ThreadInfo info = (ThreadInfo)infoObj; ThreadInfo info = (ThreadInfo)infoObj;
info.Result = CacheSystem.CheckContentIntegrity(info.FilePath, info.Bundle.FileSize, info.Bundle.FileCRC); info.Result = CacheSystem.VerifyBundle(info.Bundle, CacheSystem.InitVerifyLevel);
_syncContext.Post(VerifyCallback, info); _syncContext.Post(VerifyCallback, info);
} }
private void VerifyCallback(object obj) private void VerifyCallback(object obj)
@ -140,17 +140,17 @@ namespace YooAsset
if (info.Result) if (info.Result)
{ {
VerifySuccessCount++; VerifySuccessCount++;
CacheSystem.CacheVerifyFile(info.Bundle); CacheSystem.CacheBundle(info.Bundle);
} }
else else
{ {
VerifyFailCount++; VerifyFailCount++;
YooLogger.Warning($"Failed to verify file : {info.Bundle.CachedFilePath}");
// NOTE不期望删除断点续传的资源文件 // NOTE不期望删除断点续传的资源文件
/* /*
YooLogger.Warning($"Failed to verify file : {info.FilePath}"); if (File.Exists(patchBundle.CachedBundleFilePath))
if (File.Exists(info.FilePath)) File.Delete(patchBundle.CachedBundleFilePath);
File.Delete(info.FilePath);
*/ */
} }
_verifyingList.Remove(info.Bundle); _verifyingList.Remove(info.Bundle);
@ -173,7 +173,7 @@ namespace YooAsset
foreach (var patchBundle in localPatchManifest.BundleList) foreach (var patchBundle in localPatchManifest.BundleList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -187,7 +187,7 @@ namespace YooAsset
// 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性 // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
if (weaklyUpdate) if (weaklyUpdate)
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); string filePath = patchBundle.CachedFilePath;
if (File.Exists(filePath)) if (File.Exists(filePath))
_waitingList.Add(patchBundle); _waitingList.Add(patchBundle);
else else
@ -195,7 +195,7 @@ namespace YooAsset
} }
else else
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); string filePath = patchBundle.CachedFilePath;
if (File.Exists(filePath)) if (File.Exists(filePath))
_waitingList.Add(patchBundle); _waitingList.Add(patchBundle);
} }
@ -234,22 +234,19 @@ namespace YooAsset
private void VerifyFile(PatchBundle patchBundle) private void VerifyFile(PatchBundle patchBundle)
{ {
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName); if (CacheSystem.VerifyAndCacheBundle(patchBundle, CacheSystem.InitVerifyLevel))
bool result = CacheSystem.CheckContentIntegrity(filePath, patchBundle.FileSize, patchBundle.FileCRC);
if (result)
{ {
VerifySuccessCount++; VerifySuccessCount++;
CacheSystem.CacheVerifyFile(patchBundle);
} }
else else
{ {
VerifyFailCount++; VerifyFailCount++;
YooLogger.Warning($"Failed to verify file : {patchBundle.CachedFilePath}");
// NOTE不期望删除断点续传的资源文件 // NOTE不期望删除断点续传的资源文件
/* /*
YooLogger.Warning($"Failed to verify file : {info.FilePath}"); if (File.Exists(patchBundle.CachedBundleFilePath))
if (File.Exists(info.FilePath)) File.Delete(patchBundle.CachedBundleFilePath);
File.Delete(info.FilePath);
*/ */
} }
} }

View File

@ -70,13 +70,13 @@ namespace YooAsset
public static DownloaderBase BeginDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60) public static DownloaderBase BeginDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
{ {
// 查询存在的下载器 // 查询存在的下载器
if (_downloaderDic.TryGetValue(bundleInfo.FileHash, out var downloader)) if (_downloaderDic.TryGetValue(bundleInfo.Bundle.CachedFilePath, out var downloader))
{ {
return downloader; return downloader;
} }
// 如果资源已经缓存 // 如果资源已经缓存
if (CacheSystem.ContainsVerifyFile(bundleInfo.LoadBundle)) if (CacheSystem.IsCached(bundleInfo.Bundle))
{ {
var tempDownloader = new TempDownloader(bundleInfo); var tempDownloader = new TempDownloader(bundleInfo);
return tempDownloader; return tempDownloader;
@ -84,15 +84,15 @@ namespace YooAsset
// 创建新的下载器 // 创建新的下载器
{ {
YooLogger.Log($"Beginning to download file : {bundleInfo.FileName} URL : {bundleInfo.RemoteMainURL}"); YooLogger.Log($"Beginning to download file : {bundleInfo.Bundle.FileName} URL : {bundleInfo.RemoteMainURL}");
FileUtility.CreateFileDirectory(bundleInfo.GetCacheLoadPath()); FileUtility.CreateFileDirectory(bundleInfo.Bundle.CachedFilePath);
DownloaderBase newDownloader; DownloaderBase newDownloader;
if (bundleInfo.FileSize >= _breakpointResumeFileSize) if (bundleInfo.Bundle.FileSize >= _breakpointResumeFileSize)
newDownloader = new HttpDownloader(bundleInfo); newDownloader = new HttpDownloader(bundleInfo);
else else
newDownloader = new FileDownloader(bundleInfo); newDownloader = new FileDownloader(bundleInfo);
newDownloader.SendRequest(failedTryAgain, timeout); newDownloader.SendRequest(failedTryAgain, timeout);
_downloaderDic.Add(bundleInfo.FileHash, newDownloader); _downloaderDic.Add(bundleInfo.Bundle.CachedFilePath, newDownloader);
return newDownloader; return newDownloader;
} }
} }

View File

@ -6,6 +6,7 @@ namespace YooAsset
protected enum ESteps protected enum ESteps
{ {
None, None,
CheckLocalFile,
CreateDownload, CreateDownload,
CheckDownload, CheckDownload,
TryAgain, TryAgain,
@ -54,7 +55,7 @@ namespace YooAsset
{ {
_failedTryAgain = failedTryAgain; _failedTryAgain = failedTryAgain;
_timeout = timeout; _timeout = timeout;
_steps = ESteps.CreateDownload; _steps = ESteps.CheckLocalFile;
} }
} }
public abstract void Update(); public abstract void Update();

View File

@ -29,6 +29,19 @@ namespace YooAsset
if (IsDone()) if (IsDone())
return; return;
// 检测本地文件
if (_steps == ESteps.CheckLocalFile)
{
if (CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High))
{
_steps = ESteps.Succeed;
}
else
{
_steps = ESteps.CreateDownload;
}
}
// 创建下载器 // 创建下载器
if (_steps == ESteps.CreateDownload) if (_steps == ESteps.CreateDownload)
{ {
@ -42,7 +55,7 @@ namespace YooAsset
_requestURL = GetRequestURL(); _requestURL = GetRequestURL();
_webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET); _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
DownloadHandlerFile handler = new DownloadHandlerFile(_bundleInfo.GetCacheLoadPath()); DownloadHandlerFile handler = new DownloadHandlerFile(_bundleInfo.Bundle.CachedFilePath);
handler.removeFileOnAbort = true; handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler; _webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true; _webRequest.disposeDownloadHandlerOnDispose = true;
@ -61,8 +74,9 @@ namespace YooAsset
return; return;
} }
// 检查网络错误
bool hasError = false; bool hasError = false;
// 检查网络错误
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success) if (_webRequest.result != UnityWebRequest.Result.Success)
{ {
@ -80,22 +94,18 @@ namespace YooAsset
// 检查文件完整性 // 检查文件完整性
if (hasError == false) if (hasError == false)
{ {
// 注意:如果文件验证失败需要删除文件 if (CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High) == false)
if (CacheSystem.CheckContentIntegrity(_bundleInfo.GetCacheLoadPath(), _bundleInfo.FileSize, _bundleInfo.FileCRC) == false)
{ {
hasError = true; hasError = true;
_lastError = $"Verification failed"; _lastError = $"Verify bundle content failed : {_bundleInfo.Bundle.FileName}";
} }
} }
if (hasError == false) // 如果下载失败
if (hasError)
{ {
_steps = ESteps.Succeed; // 下载失败后删除文件
CacheSystem.CacheVerifyFile(_bundleInfo.LoadBundle); string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
}
else
{
string cacheFilePath = _bundleInfo.GetCacheLoadPath();
if (File.Exists(cacheFilePath)) if (File.Exists(cacheFilePath))
File.Delete(cacheFilePath); File.Delete(cacheFilePath);
@ -111,6 +121,11 @@ namespace YooAsset
_steps = ESteps.Failed; _steps = ESteps.Failed;
} }
} }
else
{
_lastError = string.Empty;
_steps = ESteps.Succeed;
}
// 释放下载器 // 释放下载器
DisposeWebRequest(); DisposeWebRequest();

View File

@ -21,8 +21,6 @@ namespace YooAsset
private bool _running = true; private bool _running = true;
private string _url; private string _url;
private string _savePath; private string _savePath;
private string _fileName;
private string _fileCRC;
private long _fileSize; private long _fileSize;
private int _timeout; private int _timeout;
@ -50,12 +48,10 @@ namespace YooAsset
/// <summary> /// <summary>
/// 开始下载 /// 开始下载
/// </summary> /// </summary>
public void Run(string url, string savePath, string fileName, string fileCRC, long fileSize, int timeout) public void Run(string url, string savePath, long fileSize, int timeout)
{ {
_url = url; _url = url;
_savePath = savePath; _savePath = savePath;
_fileName = fileName;
_fileCRC = fileCRC;
_fileSize = fileSize; _fileSize = fileSize;
_timeout = timeout; _timeout = timeout;
@ -153,22 +149,6 @@ namespace YooAsset
fileStream.Close(); fileStream.Close();
} }
// 验证下载文件完整性
if (DownloadedBytes == (ulong)_fileSize)
{
bool verfiyResult = CacheSystem.CheckContentIntegrity(_savePath, _fileSize, _fileCRC);
if (verfiyResult == false)
{
Error = $"Verify download content failed : {_fileName}";
if (File.Exists(_savePath))
File.Delete(_savePath);
}
}
else
{
Error = $"Download content is incomplete : {_fileName}";
}
IsDone = true; IsDone = true;
} }
} }
@ -188,6 +168,20 @@ namespace YooAsset
if (IsDone()) if (IsDone())
return; return;
// 检测本地文件
if (_steps == ESteps.CheckLocalFile)
{
if (CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High))
{
_steps = ESteps.Succeed;
}
else
{
_steps = ESteps.CreateDownload;
}
}
// 创建下载器
if (_steps == ESteps.CreateDownload) if (_steps == ESteps.CreateDownload)
{ {
// 重置变量 // 重置变量
@ -197,10 +191,11 @@ namespace YooAsset
_requestURL = GetRequestURL(); _requestURL = GetRequestURL();
_threadDownloader = new ThreadDownloader(); _threadDownloader = new ThreadDownloader();
_threadDownloader.Run(_requestURL, _bundleInfo.GetCacheLoadPath(), _bundleInfo.FileName, _bundleInfo.FileCRC, _bundleInfo.FileSize, _timeout); _threadDownloader.Run(_requestURL, _bundleInfo.Bundle.CachedFilePath, _bundleInfo.Bundle.FileSize, _timeout);
_steps = ESteps.CheckDownload; _steps = ESteps.CheckDownload;
} }
// 检测下载结果
if (_steps == ESteps.CheckDownload) if (_steps == ESteps.CheckDownload)
{ {
_downloadProgress = _threadDownloader.DownloadProgress; _downloadProgress = _threadDownloader.DownloadProgress;
@ -208,10 +203,35 @@ namespace YooAsset
if (_threadDownloader.IsDone == false) if (_threadDownloader.IsDone == false)
return; return;
bool hasError = false;
// 检查下载错误
if (_threadDownloader.HasError()) if (_threadDownloader.HasError())
{ {
hasError = true;
_lastError = _threadDownloader.Error; _lastError = _threadDownloader.Error;
}
// 检查文件完整性
if (hasError == false)
{
if (CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High) == false)
{
hasError = true;
_lastError = $"Verify bundle content failed : {_bundleInfo.Bundle.FileName}";
}
else
{
// 验证失败后删除文件
string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
if (File.Exists(cacheFilePath))
File.Delete(cacheFilePath);
}
}
// 如果下载失败
if (hasError)
{
// 失败后重新尝试 // 失败后重新尝试
if (_failedTryAgain > 0) if (_failedTryAgain > 0)
{ {
@ -226,7 +246,7 @@ namespace YooAsset
} }
else else
{ {
CacheSystem.CacheVerifyFile(_bundleInfo.LoadBundle); _lastError = string.Empty;
_steps = ESteps.Succeed; _steps = ESteps.Succeed;
} }
} }

View File

@ -6,7 +6,7 @@ namespace YooAsset
public TempDownloader(BundleInfo bundleInfo) : base(bundleInfo) public TempDownloader(BundleInfo bundleInfo) : base(bundleInfo)
{ {
_downloadProgress = 1f; _downloadProgress = 1f;
_downloadedBytes = (ulong)bundleInfo.FileSize; _downloadedBytes = (ulong)bundleInfo.Bundle.FileSize;
_steps = ESteps.Succeed; _steps = ESteps.Succeed;
} }

View File

@ -12,22 +12,9 @@ namespace YooAsset
LoadFromEditor, LoadFromEditor,
} }
public readonly PatchBundle LoadBundle; public readonly PatchBundle Bundle;
public readonly ELoadMode LoadMode; public readonly ELoadMode LoadMode;
private string _streamingPath;
private string _cachePath;
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName { private set; get; }
/// <summary>
/// 文件名称
/// </summary>
public string FileName { private set; get; }
/// <summary> /// <summary>
/// 远端下载地址 /// 远端下载地址
/// </summary> /// </summary>
@ -43,147 +30,35 @@ namespace YooAsset
/// </summary> /// </summary>
public string EditorAssetPath { private set; get; } public string EditorAssetPath { private set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public string FileHash
{
get
{
if (LoadBundle == null)
return string.Empty;
else
return LoadBundle.FileHash;
}
}
/// <summary>
/// 校验的CRC
/// </summary>
public string FileCRC
{
get
{
if (LoadBundle == null)
return string.Empty;
else
return LoadBundle.FileCRC;
}
}
/// <summary>
/// 文件大小
/// </summary>
public long FileSize
{
get
{
if (LoadBundle == null)
return 0;
else
return LoadBundle.FileSize;
}
}
/// <summary>
/// 是否为加密文件
/// </summary>
public bool IsEncrypted
{
get
{
if (LoadBundle == null)
return false;
else
return LoadBundle.IsEncrypted;
}
}
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile
{
get
{
if (LoadBundle == null)
return false;
else
return LoadBundle.IsRawFile;
}
}
/// <summary>
/// 身份是否无效
/// </summary>
public bool IsInvalid
{
get
{
return LoadBundle == null;
}
}
private BundleInfo() private BundleInfo()
{ {
} }
public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode, string mainURL, string fallbackURL) public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode, string mainURL, string fallbackURL)
{ {
LoadBundle = patchBundle; Bundle = patchBundle;
LoadMode = loadMode; LoadMode = loadMode;
BundleName = patchBundle.BundleName;
FileName = patchBundle.FileName;
RemoteMainURL = mainURL; RemoteMainURL = mainURL;
RemoteFallbackURL = fallbackURL; RemoteFallbackURL = fallbackURL;
EditorAssetPath = string.Empty; EditorAssetPath = string.Empty;
} }
public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode, string editorAssetPath) public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode, string editorAssetPath)
{ {
LoadBundle = patchBundle; Bundle = patchBundle;
LoadMode = loadMode; LoadMode = loadMode;
BundleName = patchBundle.BundleName;
FileName = patchBundle.FileName;
RemoteMainURL = string.Empty; RemoteMainURL = string.Empty;
RemoteFallbackURL = string.Empty; RemoteFallbackURL = string.Empty;
EditorAssetPath = editorAssetPath; EditorAssetPath = editorAssetPath;
} }
public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode) public BundleInfo(PatchBundle patchBundle, ELoadMode loadMode)
{ {
LoadBundle = patchBundle; Bundle = patchBundle;
LoadMode = loadMode; LoadMode = loadMode;
BundleName = patchBundle.BundleName;
FileName = patchBundle.FileName;
RemoteMainURL = string.Empty; RemoteMainURL = string.Empty;
RemoteFallbackURL = string.Empty; RemoteFallbackURL = string.Empty;
EditorAssetPath = string.Empty; EditorAssetPath = string.Empty;
} }
/// <summary>
/// 获取流文件夹的加载路径
/// </summary>
public string GetStreamingLoadPath()
{
if (LoadBundle == null)
return string.Empty;
if (string.IsNullOrEmpty(_streamingPath))
_streamingPath = PathHelper.MakeStreamingLoadPath(LoadBundle.FileName);
return _streamingPath;
}
/// <summary>
/// 获取缓存文件夹的加载路径
/// </summary>
public string GetCacheLoadPath()
{
if (LoadBundle == null)
return string.Empty;
if (string.IsNullOrEmpty(_cachePath))
_cachePath = SandboxHelper.MakeCacheFilePath(LoadBundle.FileName);
return _cachePath;
}
/// <summary> /// <summary>
/// 是否为JAR包内文件 /// 是否为JAR包内文件

View File

@ -86,7 +86,7 @@ namespace YooAsset
TotalDownloadCount = downloadList.Count; TotalDownloadCount = downloadList.Count;
foreach (var patchBundle in downloadList) foreach (var patchBundle in downloadList)
{ {
TotalDownloadBytes += patchBundle.FileSize; TotalDownloadBytes += patchBundle.Bundle.FileSize;
} }
} }
} }
@ -138,7 +138,7 @@ namespace YooAsset
// 下载成功 // 下载成功
_removeList.Add(downloader); _removeList.Add(downloader);
CurrentDownloadCount++; CurrentDownloadCount++;
CurrentDownloadBytes += bundleInfo.FileSize; CurrentDownloadBytes += bundleInfo.Bundle.FileSize;
} }
// 移除已经完成的下载器(无论成功或失败) // 移除已经完成的下载器(无论成功或失败)
@ -170,7 +170,7 @@ namespace YooAsset
var operation = DownloadSystem.BeginDownload(bundleInfo, _failedTryAgain); var operation = DownloadSystem.BeginDownload(bundleInfo, _failedTryAgain);
_downloaders.Add(operation); _downloaders.Add(operation);
_downloadList.RemoveAt(index); _downloadList.RemoveAt(index);
OnStartDownloadFileCallback?.Invoke(bundleInfo.BundleName, bundleInfo.FileSize); OnStartDownloadFileCallback?.Invoke(bundleInfo.Bundle.BundleName, bundleInfo.Bundle.FileSize);
} }
} }
@ -180,7 +180,7 @@ namespace YooAsset
if (_failedList.Count > 0) if (_failedList.Count > 0)
{ {
var failedDownloader = _failedList[0]; var failedDownloader = _failedList[0];
string fileName = failedDownloader.GetBundleInfo().BundleName; string fileName = failedDownloader.GetBundleInfo().Bundle.BundleName;
Error = $"Failed to download file : {fileName}"; Error = $"Failed to download file : {fileName}";
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;

View File

@ -198,7 +198,7 @@ namespace YooAsset
foreach (var patchBundle in _remotePatchManifest.BundleList) foreach (var patchBundle in _remotePatchManifest.BundleList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -209,16 +209,6 @@ namespace YooAsset
continue; continue;
} }
// 注意:通过比对文件大小做快速的文件校验!
// 注意:在初始化的时候会去做最终校验!
string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
if (File.Exists(filePath))
{
long fileSize = FileUtility.GetFileSize(filePath);
if (fileSize == patchBundle.FileSize)
continue;
}
downloadList.Add(patchBundle); downloadList.Add(patchBundle);
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.IO;
namespace YooAsset namespace YooAsset
{ {
@ -11,11 +12,6 @@ namespace YooAsset
/// </summary> /// </summary>
public string BundleName; public string BundleName;
/// <summary>
/// 内容哈希值
/// </summary>
public string ContentHash;
/// <summary> /// <summary>
/// 文件哈希值 /// 文件哈希值
/// </summary> /// </summary>
@ -62,11 +58,43 @@ namespace YooAsset
/// </summary> /// </summary>
public string FileName { private set; get; } public string FileName { private set; get; }
/// <summary>
/// 缓存文件路径
/// </summary>
private string _cachedFilePath;
public string CachedFilePath
{
get
{
if (string.IsNullOrEmpty(_cachedFilePath) == false)
return _cachedFilePath;
public PatchBundle(string bundleName, string contentHash, string fileHash, string fileCRC, long fileSize, string[] tags) string cacheRoot = SandboxHelper.GetCacheFolderPath();
_cachedFilePath = $"{cacheRoot}/{FileName}";
return _cachedFilePath;
}
}
/// <summary>
/// 内置文件路径
/// </summary>
private string _streamingFilePath;
public string StreamingFilePath
{
get
{
if (string.IsNullOrEmpty(_streamingFilePath) == false)
return _streamingFilePath;
_streamingFilePath = PathHelper.MakeStreamingLoadPath(FileName);
return _streamingFilePath;
}
}
public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, string[] tags)
{ {
BundleName = bundleName; BundleName = bundleName;
ContentHash = contentHash;
FileHash = fileHash; FileHash = fileHash;
FileCRC = fileCRC; FileCRC = fileCRC;
FileSize = fileSize; FileSize = fileSize;

View File

@ -131,7 +131,7 @@ namespace YooAsset
foreach (var patchBundle in LocalPatchManifest.BundleList) foreach (var patchBundle in LocalPatchManifest.BundleList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -163,7 +163,7 @@ namespace YooAsset
foreach (var patchBundle in LocalPatchManifest.BundleList) foreach (var patchBundle in LocalPatchManifest.BundleList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -233,7 +233,7 @@ namespace YooAsset
foreach (var patchBundle in checkList) foreach (var patchBundle in checkList)
{ {
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 忽略APP资源 // 忽略APP资源
@ -269,7 +269,7 @@ namespace YooAsset
continue; continue;
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
// 查询DLC资源 // 查询DLC资源
@ -279,7 +279,7 @@ namespace YooAsset
} }
} }
return ConvertToUnpackList(downloadList); return PatchHelper.ConvertToUnpackList(downloadList);
} }
/// <summary> /// <summary>
@ -301,13 +301,13 @@ namespace YooAsset
continue; continue;
// 忽略缓存文件 // 忽略缓存文件
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
continue; continue;
downloadList.Add(patchBundle); downloadList.Add(patchBundle);
} }
return ConvertToUnpackList(downloadList); return PatchHelper.ConvertToUnpackList(downloadList);
} }
// WEB相关 // WEB相关
@ -339,26 +339,6 @@ namespace YooAsset
return bundleInfo; return bundleInfo;
} }
// 解压相关
public List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList)
{
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
foreach (var patchBundle in unpackList)
{
var bundleInfo = ConvertToUnpackInfo(patchBundle);
result.Add(bundleInfo);
}
return result;
}
public BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
{
// 注意:我们把流加载路径指定为远端下载地址
string streamingPath = PathHelper.MakeStreamingLoadPath(patchBundle.FileName);
streamingPath = PathHelper.ConvertToWWWPath(streamingPath);
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromRemote, streamingPath, streamingPath);
return bundleInfo;
}
// 设置资源清单 // 设置资源清单
internal void SetAppPatchManifest(PatchManifest patchManifest) internal void SetAppPatchManifest(PatchManifest patchManifest)
{ {
@ -377,7 +357,7 @@ namespace YooAsset
throw new Exception("Should never get here !"); throw new Exception("Should never get here !");
// 查询沙盒资源 // 查询沙盒资源
if (CacheSystem.ContainsVerifyFile(patchBundle)) if (CacheSystem.IsCached(patchBundle))
{ {
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache); BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache);
return bundleInfo; return bundleInfo;

View File

@ -43,8 +43,18 @@ namespace YooAsset
if (patchBundle == null) if (patchBundle == null)
throw new Exception("Should never get here !"); throw new Exception("Should never get here !");
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming); // 查询沙盒资源
return bundleInfo; if (CacheSystem.IsCached(patchBundle))
{
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache);
return bundleInfo;
}
// 查询APP资源
{
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming);
return bundleInfo;
}
} }
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo) BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
{ {

View File

@ -5,7 +5,6 @@ namespace YooAsset
{ {
public string BundleName; public string BundleName;
public string FileHash; public string FileHash;
public string FileCRC;
} }
public interface IDecryptionServices public interface IDecryptionServices

View File

@ -109,14 +109,6 @@ namespace YooAsset
{ {
return PathHelper.MakePersistentLoadPath(CacheFolderName); return PathHelper.MakePersistentLoadPath(CacheFolderName);
} }
/// <summary>
/// 获取缓存文件的存储路径
/// </summary>
public static string MakeCacheFilePath(string fileName)
{
return PathHelper.MakePersistentLoadPath($"{CacheFolderName}/{fileName}");
}
} }
/// <summary> /// <summary>
@ -140,5 +132,26 @@ namespace YooAsset
} }
return result.ToArray(); return result.ToArray();
} }
/// <summary>
/// 资源解压相关
/// </summary>
public static List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList)
{
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
foreach (var patchBundle in unpackList)
{
var bundleInfo = ConvertToUnpackInfo(patchBundle);
result.Add(bundleInfo);
}
return result;
}
public static BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
{
// 注意:我们把流加载路径指定为远端下载地址
string streamingPath = PathHelper.ConvertToWWWPath(patchBundle.StreamingFilePath);
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
return bundleInfo;
}
} }
} }

View File

@ -127,7 +127,7 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 创建文件 /// 创建文件(如果已经存在则删除旧文件)
/// </summary> /// </summary>
public static void CreateFile(string filePath, string content) public static void CreateFile(string filePath, string content)
{ {

View File

@ -205,6 +205,11 @@ namespace YooAsset
CacheSystem.Initialize(hostPlayModeParameters.VerifyLevel); CacheSystem.Initialize(hostPlayModeParameters.VerifyLevel);
DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize); DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize);
} }
else
{
CacheSystem.Initialize(EVerifyLevel.Low);
DownloadSystem.Initialize(int.MaxValue);
}
// 初始化资源系统 // 初始化资源系统
InitializationOperation initializeOperation; InitializationOperation initializeOperation;
@ -518,7 +523,7 @@ namespace YooAsset
} }
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo); BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo);
if (bundleInfo.IsRawFile == false) if (bundleInfo.Bundle.IsRawFile == false)
{ {
string error = $"Cannot load asset bundle file using {nameof(GetRawFileAsync)} interfaces !"; string error = $"Cannot load asset bundle file using {nameof(GetRawFileAsync)} interfaces !";
YooLogger.Warning(error); YooLogger.Warning(error);