+2
-2
@@ -100,13 +100,13 @@ namespace YooAsset
|
||||
DefaultDownloadFileOperation newDownloader;
|
||||
if (bundle.FileSize >= _fileSystem.ResumeDownloadMinimumSize)
|
||||
{
|
||||
newDownloader = new DownloadResumeFileOperation(_fileSystem, _fileSystem, bundle, param, _fileSystem.ResumeDownloadResponseCodes);
|
||||
newDownloader = new DownloadResumeFileOperation(_fileSystem, bundle, param);
|
||||
newDownloader.Reference();
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDownloader = new DownloadNormalFileOperation(_fileSystem, _fileSystem, bundle, param);
|
||||
newDownloader = new DownloadNormalFileOperation(_fileSystem, bundle, param);
|
||||
newDownloader.Reference();
|
||||
_downloaders.Add(bundle.BundleGUID, newDownloader);
|
||||
}
|
||||
|
||||
+97
-81
@@ -2,7 +2,6 @@
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -10,18 +9,18 @@ namespace YooAsset
|
||||
/// 缓存文件系统
|
||||
/// 说明:正在进行的下载器会在ResourcePackage销毁的时候执行Abort操作!
|
||||
/// </summary>
|
||||
internal class DefaultCacheFileSystem : IFileSystem, ICacheSystem
|
||||
internal class DefaultCacheFileSystem : IFileSystem
|
||||
{
|
||||
protected readonly Dictionary<string, CacheWrapper> _wrappers = new Dictionary<string, CacheWrapper>(10000);
|
||||
protected readonly Dictionary<string, string> _dataFilePaths = new Dictionary<string, string>(10000);
|
||||
protected readonly Dictionary<string, string> _infoFilePaths = new Dictionary<string, string>(10000);
|
||||
protected readonly Dictionary<string, RecordFileElement> _wrappers = new Dictionary<string, RecordFileElement>(10000);
|
||||
protected readonly Dictionary<string, string> _bundleDataFilePaths = new Dictionary<string, string>(10000);
|
||||
protected readonly Dictionary<string, string> _bundleInfoFilePaths = new Dictionary<string, string>(10000);
|
||||
protected readonly Dictionary<string, string> _tempFilePaths = new Dictionary<string, string>(10000);
|
||||
protected DefaultCacheDownloadCenter _downloadCenter;
|
||||
|
||||
protected string _packageRoot;
|
||||
protected string _cacheFileRoot;
|
||||
protected string _tempFileRoot;
|
||||
protected string _manifestFileRoot;
|
||||
protected string _tempFilesRoot;
|
||||
protected string _cacheBundleFilesRoot;
|
||||
protected string _cacheManifestFilesRoot;
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
@@ -114,30 +113,42 @@ namespace YooAsset
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
public virtual FSClearCacheBundleFilesOperation ClearCacheBundleFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
|
||||
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, string clearMode, object clearParam)
|
||||
{
|
||||
if (clearMode == EFileClearMode.ClearAllBundleFiles.ToString())
|
||||
{
|
||||
var operation = new ClearAllCacheFilesOperation(this);
|
||||
var operation = new ClearAllCacheBundleFilesOperation(this);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
else if (clearMode == EFileClearMode.ClearUnusedBundleFiles.ToString())
|
||||
{
|
||||
var operation = new ClearUnusedCacheFilesOperation(this, manifest);
|
||||
var operation = new ClearUnusedCacheBundleFilesOperation(this, manifest);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
else if (clearMode == EFileClearMode.ClearBundleFilesByTags.ToString())
|
||||
{
|
||||
var operation = new ClearCacheFilesByTagsOperaiton(this, manifest, clearParam);
|
||||
var operation = new ClearCacheBundleFilesByTagsOperaiton(this, manifest, clearParam);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
else if (clearMode == EFileClearMode.ClearAllManifestFiles.ToString())
|
||||
{
|
||||
var operation = new ClearAllCacheManifestFilesOperation(this);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
else if (clearMode == EFileClearMode.ClearUnusedManifestFiles.ToString())
|
||||
{
|
||||
var operation = new ClearUnusedCacheManifestFilesOperation(this, manifest);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error = $"Invalid clear mode : {clearMode}";
|
||||
var operation = new FSClearCacheBundleFilesCompleteOperation(error);
|
||||
var operation = new FSClearCacheFilesCompleteOperation(error);
|
||||
OperationSystem.StartOperation(PackageName, operation);
|
||||
return operation;
|
||||
}
|
||||
@@ -217,9 +228,9 @@ namespace YooAsset
|
||||
else
|
||||
_packageRoot = packageRoot;
|
||||
|
||||
_cacheFileRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.SaveFilesFolderName);
|
||||
_tempFileRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
||||
_manifestFileRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||
_cacheBundleFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.BundleFilesFolderName);
|
||||
_tempFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.TempFilesFolderName);
|
||||
_cacheManifestFilesRoot = PathUtility.Combine(_packageRoot, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
|
||||
_downloadCenter = new DefaultCacheDownloadCenter(this);
|
||||
}
|
||||
public virtual void OnUpdate()
|
||||
@@ -257,7 +268,7 @@ namespace YooAsset
|
||||
|
||||
public virtual string GetBundleFilePath(PackageBundle bundle)
|
||||
{
|
||||
return GetCacheFileLoadPath(bundle);
|
||||
return GetCacheBundleFileLoadPath(bundle);
|
||||
}
|
||||
public virtual byte[] ReadBundleFileData(PackageBundle bundle)
|
||||
{
|
||||
@@ -272,7 +283,7 @@ namespace YooAsset
|
||||
return null;
|
||||
}
|
||||
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
var fileInfo = new DecryptFileInfo()
|
||||
{
|
||||
BundleName = bundle.BundleName,
|
||||
@@ -283,7 +294,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
return FileUtility.ReadAllBytes(filePath);
|
||||
}
|
||||
}
|
||||
@@ -300,7 +311,7 @@ namespace YooAsset
|
||||
return null;
|
||||
}
|
||||
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
var fileInfo = new DecryptFileInfo()
|
||||
{
|
||||
BundleName = bundle.BundleName,
|
||||
@@ -311,85 +322,82 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
return FileUtility.ReadAllText(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
#region 缓存系统
|
||||
public string GetCacheFileRoot()
|
||||
{
|
||||
return _cacheFileRoot;
|
||||
}
|
||||
public string GetTempFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_tempFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
filePath = PathUtility.Combine(_tempFileRoot, bundle.BundleGUID);
|
||||
_tempFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetDataFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_dataFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(_cacheFileRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.SaveBundleDataFileName);
|
||||
if (AppendFileExtension)
|
||||
filePath += bundle.FileExtension;
|
||||
_dataFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetInfoFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_infoFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(_cacheFileRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.SaveBundleInfoFileName);
|
||||
_infoFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
#region 缓存相关
|
||||
public List<string> GetAllCachedBundleGUIDs()
|
||||
{
|
||||
return _wrappers.Keys.ToList();
|
||||
}
|
||||
|
||||
public bool IsRecordFile(string bundleGUID)
|
||||
public string GetTempFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_tempFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
filePath = PathUtility.Combine(_tempFilesRoot, bundle.BundleGUID);
|
||||
_tempFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetBundleDataFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_bundleDataFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleDataFileName);
|
||||
if (AppendFileExtension)
|
||||
filePath += bundle.FileExtension;
|
||||
_bundleDataFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetBundleInfoFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_bundleInfoFilePaths.TryGetValue(bundle.BundleGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(_cacheBundleFilesRoot, folderName, bundle.BundleGUID, DefaultCacheFileSystemDefine.BundleInfoFileName);
|
||||
_bundleInfoFilePaths.Add(bundle.BundleGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public bool IsRecordBundleFile(string bundleGUID)
|
||||
{
|
||||
return _wrappers.ContainsKey(bundleGUID);
|
||||
}
|
||||
public bool RecordFile(string bundleGUID, CacheWrapper wrapper)
|
||||
public bool RecordBundleFile(string bundleGUID, RecordFileElement element)
|
||||
{
|
||||
if (_wrappers.ContainsKey(bundleGUID))
|
||||
{
|
||||
YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has element : {bundleGUID}");
|
||||
YooLogger.Error($"{nameof(DefaultCacheFileSystem)} has record file element : {bundleGUID}");
|
||||
return false;
|
||||
}
|
||||
|
||||
_wrappers.Add(bundleGUID, wrapper);
|
||||
_wrappers.Add(bundleGUID, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
public EFileVerifyResult VerifyCacheFile(PackageBundle bundle)
|
||||
{
|
||||
if (_wrappers.TryGetValue(bundle.BundleGUID, out CacheWrapper wrapper) == false)
|
||||
if (_wrappers.TryGetValue(bundle.BundleGUID, out RecordFileElement wrapper) == false)
|
||||
return EFileVerifyResult.CacheNotFound;
|
||||
|
||||
EFileVerifyResult result = FileVerifyHelper.FileVerify(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EFileVerifyLevel.High);
|
||||
return result;
|
||||
}
|
||||
public bool WriteCacheFile(PackageBundle bundle, string copyPath)
|
||||
public bool WriteCacheBundleFile(PackageBundle bundle, string copyPath)
|
||||
{
|
||||
if (_wrappers.ContainsKey(bundle.BundleGUID))
|
||||
{
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
|
||||
string infoFilePath = GetInfoFilePath(bundle);
|
||||
string dataFilePath = GetDataFilePath(bundle);
|
||||
string infoFilePath = GetBundleInfoFilePath(bundle);
|
||||
string dataFilePath = GetBundleDataFilePath(bundle);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -405,7 +413,7 @@ namespace YooAsset
|
||||
fileInfo.CopyTo(dataFilePath);
|
||||
|
||||
// 写入文件信息
|
||||
WriteInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
|
||||
WriteBundleInfoFile(infoFilePath, bundle.FileCRC, bundle.FileSize);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -413,12 +421,12 @@ namespace YooAsset
|
||||
return false;
|
||||
}
|
||||
|
||||
var wrapper = new CacheWrapper(infoFilePath, dataFilePath, bundle.FileCRC, bundle.FileSize);
|
||||
return RecordFile(bundle.BundleGUID, wrapper);
|
||||
var recordFileElement = new RecordFileElement(infoFilePath, dataFilePath, bundle.FileCRC, bundle.FileSize);
|
||||
return RecordBundleFile(bundle.BundleGUID, recordFileElement);
|
||||
}
|
||||
public bool DeleteCacheFile(string bundleGUID)
|
||||
public bool DeleteCacheBundleFile(string bundleGUID)
|
||||
{
|
||||
if (_wrappers.TryGetValue(bundleGUID, out CacheWrapper wrapper))
|
||||
if (_wrappers.TryGetValue(bundleGUID, out RecordFileElement wrapper))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -442,7 +450,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
private readonly BufferWriter _sharedBuffer = new BufferWriter(1024);
|
||||
public void WriteInfoFile(string filePath, string dataFileCRC, long dataFileSize)
|
||||
public void WriteBundleInfoFile(string filePath, string dataFileCRC, long dataFileSize)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
@@ -453,7 +461,7 @@ namespace YooAsset
|
||||
fs.Flush();
|
||||
}
|
||||
}
|
||||
public void ReadInfoFile(string filePath, out string dataFileCRC, out long dataFileSize)
|
||||
public void ReadBundleInfoFile(string filePath, out string dataFileCRC, out long dataFileSize)
|
||||
{
|
||||
byte[] binaryData = FileUtility.ReadAllBytes(filePath);
|
||||
BufferReader buffer = new BufferReader(binaryData);
|
||||
@@ -477,23 +485,31 @@ namespace YooAsset
|
||||
|
||||
return PathUtility.Combine(rootDirectory, packageName);
|
||||
}
|
||||
public string GetCacheFileLoadPath(PackageBundle bundle)
|
||||
public string GetCacheBundleFileLoadPath(PackageBundle bundle)
|
||||
{
|
||||
return GetDataFilePath(bundle);
|
||||
return GetBundleDataFilePath(bundle);
|
||||
}
|
||||
public string GetCachePackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_manifestFileRoot, fileName);
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
|
||||
}
|
||||
public string GetCachePackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(_manifestFileRoot, fileName);
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, fileName);
|
||||
}
|
||||
public string GetSandboxAppFootPrintFilePath()
|
||||
{
|
||||
return PathUtility.Combine(_manifestFileRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName);
|
||||
return PathUtility.Combine(_cacheManifestFilesRoot, DefaultCacheFileSystemDefine.AppFootPrintFileName);
|
||||
}
|
||||
public string GetCacheBundleFilesRoot()
|
||||
{
|
||||
return _cacheBundleFilesRoot;
|
||||
}
|
||||
public string GetCacheManifestFilesRoot()
|
||||
{
|
||||
return _cacheManifestFilesRoot;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -501,9 +517,9 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public void DeleteAllManifestFiles()
|
||||
{
|
||||
if (Directory.Exists(_manifestFileRoot))
|
||||
if (Directory.Exists(_cacheManifestFilesRoot))
|
||||
{
|
||||
Directory.Delete(_manifestFileRoot, true);
|
||||
Directory.Delete(_cacheManifestFilesRoot, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +528,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public DecryptResult LoadEncryptedAssetBundle(PackageBundle bundle)
|
||||
{
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
var fileInfo = new DecryptFileInfo()
|
||||
{
|
||||
BundleName = bundle.BundleName,
|
||||
@@ -527,7 +543,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public DecryptResult LoadEncryptedAssetBundleAsync(PackageBundle bundle)
|
||||
{
|
||||
string filePath = GetCacheFileLoadPath(bundle);
|
||||
string filePath = GetCacheBundleFileLoadPath(bundle);
|
||||
var fileInfo = new DecryptFileInfo()
|
||||
{
|
||||
BundleName = bundle.BundleName,
|
||||
|
||||
+9
-9
@@ -4,27 +4,27 @@ namespace YooAsset
|
||||
internal class DefaultCacheFileSystemDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// 保存的数据文件名称
|
||||
/// 数据文件名称
|
||||
/// </summary>
|
||||
public const string SaveBundleDataFileName = "__data";
|
||||
public const string BundleDataFileName = "__data";
|
||||
|
||||
/// <summary>
|
||||
/// 保存的信息文件名称
|
||||
/// 信息文件名称
|
||||
/// </summary>
|
||||
public const string SaveBundleInfoFileName = "__info";
|
||||
public const string BundleInfoFileName = "__info";
|
||||
|
||||
/// <summary>
|
||||
/// 保存的资源文件的文件夹名称
|
||||
/// 资源文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string SaveFilesFolderName = "CacheFiles";
|
||||
public const string BundleFilesFolderName = "BundleFiles";
|
||||
|
||||
/// <summary>
|
||||
/// 下载的临时文件的文件夹名称
|
||||
/// 临时文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string TempFilesFolderName = "CacheTempFiles";
|
||||
public const string TempFilesFolderName = "TempFiles";
|
||||
|
||||
/// <summary>
|
||||
/// 保存的清单文件的文件夹名称
|
||||
/// 清单文件的文件夹名称
|
||||
/// </summary>
|
||||
public const string ManifestFilesFolderName = "ManifestFiles";
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da6402a4b93d31943b26fb99cebc0dfd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RecordFileElement
|
||||
{
|
||||
public string InfoFilePath { private set; get; }
|
||||
public string DataFilePath { private set; get; }
|
||||
public string DataFileCRC { private set; get; }
|
||||
public long DataFileSize { private set; get; }
|
||||
|
||||
public RecordFileElement(string infoFilePath, string dataFilePath, string dataFileCRC, long dataFileSize)
|
||||
{
|
||||
InfoFilePath = infoFilePath;
|
||||
DataFilePath = dataFilePath;
|
||||
DataFileCRC = dataFileCRC;
|
||||
DataFileSize = dataFileSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae2176c4ea6fbb3478bf8757def34cd7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class TempFileElement
|
||||
{
|
||||
public string TempFilePath { private set; get; }
|
||||
public string TempFileCRC { private set; get; }
|
||||
public long TempFileSize { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 注意:原子操作对象
|
||||
/// </summary>
|
||||
public volatile int Result = 0;
|
||||
|
||||
public TempFileElement(string filePath, string fileCRC, long fileSize)
|
||||
{
|
||||
TempFilePath = filePath;
|
||||
TempFileCRC = fileCRC;
|
||||
TempFileSize = fileSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 220136fdc4a13d84e97b1249cfc65f3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class VerifyFileElement
|
||||
{
|
||||
public string PackageName { private set; get; }
|
||||
public string BundleGUID { private set; get; }
|
||||
public string FileRootPath { private set; get; }
|
||||
public string DataFilePath { private set; get; }
|
||||
public string InfoFilePath { private set; get; }
|
||||
|
||||
public string DataFileCRC;
|
||||
public long DataFileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 注意:原子操作对象
|
||||
/// </summary>
|
||||
public volatile int Result = 0;
|
||||
|
||||
public VerifyFileElement(string packageName, string bundleGUID, string fileRootPath, string dataFilePath, string infoFilePath)
|
||||
{
|
||||
PackageName = packageName;
|
||||
BundleGUID = bundleGUID;
|
||||
FileRootPath = fileRootPath;
|
||||
DataFilePath = dataFilePath;
|
||||
InfoFilePath = infoFilePath;
|
||||
}
|
||||
|
||||
public void DeleteFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(FileRootPath, true);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
YooLogger.Warning($"Failed to delete cache bundle folder : {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c361449cdcbd8746ba3fb948798ae1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+2
-2
@@ -57,7 +57,7 @@ namespace YooAsset
|
||||
{
|
||||
if (_searchCacheFilesOp == null)
|
||||
{
|
||||
_searchCacheFilesOp = new SearchCacheFilesOperation(_fileSystem, _fileSystem.PackageName, _fileSystem.AppendFileExtension);
|
||||
_searchCacheFilesOp = new SearchCacheFilesOperation(_fileSystem);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _searchCacheFilesOp);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace YooAsset
|
||||
{
|
||||
if (_verifyCacheFilesOp == null)
|
||||
{
|
||||
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_fileSystem, _fileSystem.FileVerifyLevel, _searchCacheFilesOp.Result);
|
||||
_verifyCacheFilesOp = new VerifyCacheFilesOperation(_fileSystem, _searchCacheFilesOp.Result);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyCacheFilesOp);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -104,7 +104,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = _fileSystem.GetCacheFileLoadPath(_bundle);
|
||||
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
_assetBundle = AssetBundle.LoadFromFile(filePath);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
string filePath = _fileSystem.GetCacheFileLoadPath(_bundle);
|
||||
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(filePath);
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ namespace YooAsset
|
||||
|
||||
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
|
||||
// 说明:大多数情况在首次安装下载资源到沙盒内,游戏过程中切换到后台再回到游戏内有很大概率触发!
|
||||
string filePath = _fileSystem.GetCacheFileLoadPath(_bundle);
|
||||
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
byte[] fileData = FileUtility.ReadAllBytes(filePath);
|
||||
if (fileData != null && fileData.Length > 0)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ namespace YooAsset
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
_fileSystem.DeleteCacheFile(_bundle.BundleGUID);
|
||||
_fileSystem.DeleteCacheBundleFile(_bundle.BundleGUID);
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Find corrupted asset bundle file and delete : {_bundle.BundleName}";
|
||||
YooLogger.Error(Error);
|
||||
@@ -304,7 +304,7 @@ namespace YooAsset
|
||||
|
||||
if (_steps == ESteps.LoadCacheRawBundle)
|
||||
{
|
||||
string filePath = _fileSystem.GetCacheFileLoadPath(_bundle);
|
||||
string filePath = _fileSystem.GetCacheBundleFileLoadPath(_bundle);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearAllCacheBundleFilesOperation : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetAllCacheFiles,
|
||||
ClearAllCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private List<string> _allBundleGUIDs;
|
||||
private int _fileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearAllCacheBundleFilesOperation(DefaultCacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.GetAllCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetAllCacheFiles)
|
||||
{
|
||||
_allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
|
||||
_fileTotalCount = _allBundleGUIDs.Count;
|
||||
_steps = ESteps.ClearAllCacheFiles;
|
||||
YooLogger.Log($"Found all cache files count : {_fileTotalCount}");
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearAllCacheFiles)
|
||||
{
|
||||
for (int i = _allBundleGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string bundleGUID = _allBundleGUIDs[i];
|
||||
_fileSystem.DeleteCacheBundleFile(bundleGUID);
|
||||
_allBundleGUIDs.RemoveAt(i);
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_allBundleGUIDs.Count / _fileTotalCount);
|
||||
|
||||
if (_allBundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: daed187502431d347bf11bddcf8d77de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearAllCacheManifestFilesOperation : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
ClearAllCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearAllCacheManifestFilesOperation(DefaultCacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.ClearAllCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.ClearAllCacheFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 注意:如果正在下载资源清单,会有几率触发异常!
|
||||
string directoryRoot = _fileSystem.GetCacheManifestFilesRoot();
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot);
|
||||
if (directoryInfo.Exists)
|
||||
{
|
||||
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
|
||||
{
|
||||
string fileName = fileInfo.Name;
|
||||
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName)
|
||||
continue;
|
||||
|
||||
fileInfo.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Error = ex.Message;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5643382e7031ba14cbb4ab0f4a9acd94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class ClearCacheBundleFilesByTagsOperaiton : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckArgs,
|
||||
GetTagsCacheFiles,
|
||||
ClearTagsCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private readonly object _clearParam;
|
||||
private string[] _tags;
|
||||
private List<string> _clearBundleGUIDs;
|
||||
private int _clearFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearCacheBundleFilesByTagsOperaiton(DefaultCacheFileSystem fileSystem, PackageManifest manifest, object clearParam)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
_clearParam = clearParam;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.CheckArgs;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckArgs)
|
||||
{
|
||||
if (_clearParam == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "Clear param is null !";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clearParam is string)
|
||||
{
|
||||
_tags = new string[] { _clearParam as string };
|
||||
}
|
||||
else if (_clearParam is List<string>)
|
||||
{
|
||||
var tempList = _clearParam as List<string>;
|
||||
_tags = tempList.ToArray();
|
||||
}
|
||||
else if (_clearParam is string[])
|
||||
{
|
||||
_tags = _clearParam as string[];
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Invalid clear param : {_clearParam.GetType().FullName}";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.GetTagsCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.GetTagsCacheFiles)
|
||||
{
|
||||
_clearBundleGUIDs = GetTagsBundleGUIDs();
|
||||
_clearFileTotalCount = _clearBundleGUIDs.Count;
|
||||
_steps = ESteps.ClearTagsCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearTagsCacheFiles)
|
||||
{
|
||||
for (int i = _clearBundleGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string bundleGUID = _clearBundleGUIDs[i];
|
||||
_fileSystem.DeleteCacheBundleFile(bundleGUID);
|
||||
_clearBundleGUIDs.RemoveAt(i);
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_clearFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_clearBundleGUIDs.Count / _clearFileTotalCount);
|
||||
|
||||
if (_clearBundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
private List<string> GetTagsBundleGUIDs()
|
||||
{
|
||||
var allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
|
||||
List<string> result = new List<string>(allBundleGUIDs.Count);
|
||||
foreach (var bundleGUID in allBundleGUIDs)
|
||||
{
|
||||
if (_manifest.TryGetPackageBundleByBundleGUID(bundleGUID, out PackageBundle bundle))
|
||||
{
|
||||
if (bundle.HasTag(_tags))
|
||||
{
|
||||
result.Add(bundleGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c42345c14a903274fb160a813ee174dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearUnusedCacheBundleFilesOperation : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetUnusedCacheFiles,
|
||||
ClearUnusedCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private List<string> _unusedBundleGUIDs;
|
||||
private int _unusedFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearUnusedCacheBundleFilesOperation(DefaultCacheFileSystem fileSystem, PackageManifest manifest)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.GetUnusedCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetUnusedCacheFiles)
|
||||
{
|
||||
_unusedBundleGUIDs = GetUnusedBundleGUIDs();
|
||||
_unusedFileTotalCount = _unusedBundleGUIDs.Count;
|
||||
_steps = ESteps.ClearUnusedCacheFiles;
|
||||
YooLogger.Log($"Found unused cache files count : {_unusedFileTotalCount}");
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
||||
{
|
||||
for (int i = _unusedBundleGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string bundleGUID = _unusedBundleGUIDs[i];
|
||||
_fileSystem.DeleteCacheBundleFile(bundleGUID);
|
||||
_unusedBundleGUIDs.RemoveAt(i);
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_unusedFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_unusedBundleGUIDs.Count / _unusedFileTotalCount);
|
||||
|
||||
if (_unusedBundleGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetUnusedBundleGUIDs()
|
||||
{
|
||||
var allBundleGUIDs = _fileSystem.GetAllCachedBundleGUIDs();
|
||||
List<string> result = new List<string>(allBundleGUIDs.Count);
|
||||
foreach (var bundleGUID in allBundleGUIDs)
|
||||
{
|
||||
if (_manifest.IsIncludeBundleFile(bundleGUID) == false)
|
||||
{
|
||||
result.Add(bundleGUID);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be7b242f10abf524fa59e9ca0d12b052
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class ClearUnusedCacheManifestFilesOperation : FSClearCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
ClearUnusedCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly PackageManifest _manifest;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal ClearUnusedCacheManifestFilesOperation(DefaultCacheFileSystem fileSystem, PackageManifest manifest)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_manifest = manifest;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.ClearUnusedCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
string activeManifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(_manifest.PackageName, _manifest.PackageVersion);
|
||||
string activeHashFileName = YooAssetSettingsData.GetPackageHashFileName(_manifest.PackageName, _manifest.PackageVersion);
|
||||
|
||||
// 注意:如果正在下载资源清单,会有几率触发异常!
|
||||
string directoryRoot = _fileSystem.GetCacheManifestFilesRoot();
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(directoryRoot);
|
||||
if (directoryInfo.Exists)
|
||||
{
|
||||
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
|
||||
{
|
||||
string fileName = fileInfo.Name;
|
||||
if (fileName == DefaultCacheFileSystemDefine.AppFootPrintFileName)
|
||||
continue;
|
||||
if (fileName == activeManifestFileName || fileName == activeHashFileName)
|
||||
continue;
|
||||
|
||||
fileInfo.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Error = ex.Message;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d911513cf97d862448df570f0c8e9b38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 支持Unity2018版本的断点续传下载器
|
||||
/// </summary>
|
||||
internal class DownloadHandlerFileRange : DownloadHandlerScript
|
||||
{
|
||||
private string _fileSavePath;
|
||||
private long _fileTotalSize;
|
||||
private UnityWebRequest _webRequest;
|
||||
private FileStream _fileStream;
|
||||
|
||||
private long _localFileSize = 0;
|
||||
private long _curFileSize = 0;
|
||||
|
||||
|
||||
public DownloadHandlerFileRange(string fileSavePath, long fileTotalSize, UnityWebRequest webRequest) : base(new byte[1024 * 1024])
|
||||
{
|
||||
_fileSavePath = fileSavePath;
|
||||
_fileTotalSize = fileTotalSize;
|
||||
_webRequest = webRequest;
|
||||
|
||||
if (File.Exists(fileSavePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(fileSavePath);
|
||||
_localFileSize = fileInfo.Length;
|
||||
}
|
||||
|
||||
_fileStream = new FileStream(_fileSavePath, FileMode.Append, FileAccess.Write);
|
||||
_curFileSize = _localFileSize;
|
||||
}
|
||||
protected override bool ReceiveData(byte[] data, int dataLength)
|
||||
{
|
||||
if (data == null || dataLength == 0 || _webRequest.responseCode >= 400)
|
||||
return false;
|
||||
|
||||
if (_fileStream == null)
|
||||
return false;
|
||||
|
||||
_fileStream.Write(data, 0, dataLength);
|
||||
_curFileSize += dataLength;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnityWebRequest.downloadHandler.data
|
||||
/// </summary>
|
||||
protected override byte[] GetData()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnityWebRequest.downloadHandler.text
|
||||
/// </summary>
|
||||
protected override string GetText()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnityWebRequest.downloadProgress
|
||||
/// </summary>
|
||||
protected override float GetProgress()
|
||||
{
|
||||
return _fileTotalSize == 0 ? 0 : ((float)_curFileSize) / _fileTotalSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放下载句柄
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
if (_fileStream != null)
|
||||
{
|
||||
_fileStream.Flush();
|
||||
_fileStream.Dispose();
|
||||
_fileStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94254ab8e4496214884c11a891c131c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class DownloadNormalFileOperation : DefaultDownloadFileOperation
|
||||
{
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private VerifyTempFileOperation _verifyOperation;
|
||||
private bool _isReuqestLocalFile;
|
||||
private string _tempFilePath;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal DownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_isReuqestLocalFile = DownloadSystemHelper.IsRequestLocalFile(Param.MainURL);
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
|
||||
_steps = ESteps.CheckExists;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 检测文件是否存在
|
||||
if (_steps == ESteps.CheckExists)
|
||||
{
|
||||
if (_fileSystem.Exists(Bundle))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
|
||||
// 删除临时文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
// 获取请求地址
|
||||
_requestURL = GetRequestURL();
|
||||
|
||||
// 重置请求
|
||||
ResetRequestFiled();
|
||||
|
||||
// 创建下载器
|
||||
CreateWebRequest();
|
||||
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_webRequest.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查网络错误
|
||||
if (CheckRequestResult())
|
||||
_steps = ESteps.VerifyTempFile;
|
||||
else
|
||||
_steps = ESteps.TryAgain;
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
|
||||
// 验证下载文件
|
||||
if (_steps == ESteps.VerifyTempFile)
|
||||
{
|
||||
var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize);
|
||||
_verifyOperation = new VerifyTempFileOperation(element);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyOperation);
|
||||
_steps = ESteps.CheckVerifyTempFile;
|
||||
}
|
||||
|
||||
// 等待验证完成
|
||||
if (_steps == ESteps.CheckVerifyTempFile)
|
||||
{
|
||||
if (IsWaitForAsyncComplete)
|
||||
_verifyOperation.WaitForAsyncComplete();
|
||||
|
||||
if (_verifyOperation.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_verifyOperation.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{_fileSystem.GetType().FullName} failed to write file !";
|
||||
YooLogger.Error(Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
Error = _verifyOperation.Error;
|
||||
}
|
||||
|
||||
// 注意:验证完成后直接删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
//TODO 拷贝本地文件失败后不再尝试!
|
||||
if (_isReuqestLocalFile)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FailedTryAgain <= 0)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
FailedTryAgain--;
|
||||
_steps = ESteps.CreateRequest;
|
||||
YooLogger.Warning(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalOnAbort()
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
DisposeWebRequest();
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
//TODO 防止下载器挂起陷入无限死循环!
|
||||
if (_steps == ESteps.None)
|
||||
{
|
||||
InternalOnStart();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
//TODO 如果是导入或解压本地文件,执行等待完毕
|
||||
if (_isReuqestLocalFile)
|
||||
{
|
||||
InternalOnUpdate();
|
||||
if (IsDone)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExecuteWhileDone())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
//注意:引擎底层会自动调用Abort方法
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 759967d543776a0469b625eff171d235
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class DownloadResumeFileOperation : DefaultDownloadFileOperation
|
||||
{
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private DownloadHandlerFileRange _downloadHandle;
|
||||
private VerifyTempFileOperation _verifyOperation;
|
||||
private bool _isReuqestLocalFile;
|
||||
private long _fileOriginLength = 0;
|
||||
private string _tempFilePath;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal DownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_isReuqestLocalFile = DownloadSystemHelper.IsRequestLocalFile(Param.MainURL);
|
||||
_tempFilePath = _fileSystem.GetTempFilePath(Bundle);
|
||||
_steps = ESteps.CheckExists;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
// 检测文件是否存在
|
||||
if (_steps == ESteps.CheckExists)
|
||||
{
|
||||
if (_fileSystem.Exists(Bundle))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
FileUtility.CreateFileDirectory(_tempFilePath);
|
||||
|
||||
// 获取请求地址
|
||||
_requestURL = GetRequestURL();
|
||||
|
||||
// 重置变量
|
||||
ResetRequestFiled();
|
||||
|
||||
// 获取下载起始位置
|
||||
_fileOriginLength = 0;
|
||||
long fileBeginLength = -1;
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
if (fileInfo.Length >= Bundle.FileSize)
|
||||
{
|
||||
// 删除临时文件
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileBeginLength = fileInfo.Length;
|
||||
_fileOriginLength = fileBeginLength;
|
||||
DownloadedBytes = _fileOriginLength;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
CreateWebRequest(fileBeginLength);
|
||||
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = _fileOriginLength + (long)_webRequest.downloadedBytes;
|
||||
if (_webRequest.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查网络错误
|
||||
if (CheckRequestResult())
|
||||
_steps = ESteps.VerifyTempFile;
|
||||
else
|
||||
_steps = ESteps.TryAgain;
|
||||
|
||||
// 在遇到特殊错误的时候删除文件
|
||||
ClearTempFileWhenError();
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
|
||||
// 验证下载文件
|
||||
if (_steps == ESteps.VerifyTempFile)
|
||||
{
|
||||
var element = new TempFileElement(_tempFilePath, Bundle.FileCRC, Bundle.FileSize);
|
||||
_verifyOperation = new VerifyTempFileOperation(element);
|
||||
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyOperation);
|
||||
_steps = ESteps.CheckVerifyTempFile;
|
||||
}
|
||||
|
||||
// 等待验证完成
|
||||
if (_steps == ESteps.CheckVerifyTempFile)
|
||||
{
|
||||
if (IsWaitForAsyncComplete)
|
||||
_verifyOperation.WaitForAsyncComplete();
|
||||
|
||||
if (_verifyOperation.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_verifyOperation.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
if (_fileSystem.WriteCacheBundleFile(Bundle, _tempFilePath))
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
_steps = ESteps.Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error = $"{_fileSystem.GetType().FullName} failed to write file !";
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Error = _verifyOperation.Error;
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
|
||||
// 注意:验证完成后直接删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
//TODO 拷贝本地文件失败后不再尝试!
|
||||
if (_isReuqestLocalFile)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FailedTryAgain <= 0)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
FailedTryAgain--;
|
||||
_steps = ESteps.CreateRequest;
|
||||
YooLogger.Warning(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalOnAbort()
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
DisposeWebRequest();
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
//TODO 防止下载器挂起陷入无限死循环!
|
||||
if (_steps == ESteps.None)
|
||||
{
|
||||
InternalOnStart();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
//TODO 如果是导入或解压本地文件,执行等待完毕
|
||||
if (_isReuqestLocalFile)
|
||||
{
|
||||
InternalOnUpdate();
|
||||
if (IsDone)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExecuteWhileDone())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest(long beginLength)
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
var handler = new DownloadHandlerFile(_tempFilePath, true);
|
||||
handler.removeFileOnAbort = false;
|
||||
#else
|
||||
var handler = new DownloadHandlerFileRange(FileSavePath, Bundle.FileSize, _webRequest);
|
||||
_downloadHandle = handler;
|
||||
#endif
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
if (beginLength > 0)
|
||||
_webRequest.SetRequestHeader("Range", $"bytes={beginLength}-");
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_downloadHandle != null)
|
||||
{
|
||||
_downloadHandle.Cleanup();
|
||||
_downloadHandle = null;
|
||||
}
|
||||
|
||||
if (_webRequest != null)
|
||||
{
|
||||
//注意:引擎底层会自动调用Abort方法
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
private void ClearTempFileWhenError()
|
||||
{
|
||||
if (_fileSystem.ResumeDownloadResponseCodes == null)
|
||||
return;
|
||||
|
||||
//说明:如果遇到以下错误返回码,验证失败直接删除文件
|
||||
if (_fileSystem.ResumeDownloadResponseCodes.Contains(HttpCode))
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bfb785912326f942a31dc77762eb16a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class SearchCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Prepare,
|
||||
SearchFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private IEnumerator<DirectoryInfo> _filesEnumerator = null;
|
||||
private float _verifyStartTime;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 需要验证的元素
|
||||
/// </summary>
|
||||
public readonly List<VerifyFileElement> Result = new List<VerifyFileElement>(5000);
|
||||
|
||||
|
||||
internal SearchCacheFilesOperation(DefaultCacheFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.Prepare;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Prepare)
|
||||
{
|
||||
DirectoryInfo rootDirectory = new DirectoryInfo(_fileSystem.GetCacheBundleFilesRoot());
|
||||
if (rootDirectory.Exists)
|
||||
{
|
||||
var directorieInfos = rootDirectory.EnumerateDirectories();
|
||||
_filesEnumerator = directorieInfos.GetEnumerator();
|
||||
}
|
||||
_steps = ESteps.SearchFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.SearchFiles)
|
||||
{
|
||||
if (SearchFiles())
|
||||
return;
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Search cache files elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
}
|
||||
|
||||
private bool SearchFiles()
|
||||
{
|
||||
if (_filesEnumerator == null)
|
||||
return false;
|
||||
|
||||
bool isFindItem;
|
||||
while (true)
|
||||
{
|
||||
isFindItem = _filesEnumerator.MoveNext();
|
||||
if (isFindItem == false)
|
||||
break;
|
||||
|
||||
var rootFoder = _filesEnumerator.Current;
|
||||
var childDirectories = rootFoder.GetDirectories();
|
||||
foreach (var chidDirectory in childDirectories)
|
||||
{
|
||||
string bundleGUID = chidDirectory.Name;
|
||||
if (_fileSystem.IsRecordBundleFile(bundleGUID))
|
||||
continue;
|
||||
|
||||
// 创建验证元素类
|
||||
string fileRootPath = chidDirectory.FullName;
|
||||
string dataFilePath = $"{fileRootPath}/{ DefaultCacheFileSystemDefine.BundleDataFileName}";
|
||||
string infoFilePath = $"{fileRootPath}/{ DefaultCacheFileSystemDefine.BundleInfoFileName}";
|
||||
|
||||
// 存储的数据文件追加文件格式
|
||||
if (_fileSystem.AppendFileExtension)
|
||||
{
|
||||
string dataFileExtension = FindDataFileExtension(chidDirectory);
|
||||
if (string.IsNullOrEmpty(dataFileExtension) == false)
|
||||
dataFilePath += dataFileExtension;
|
||||
}
|
||||
|
||||
var element = new VerifyFileElement(_fileSystem.PackageName, bundleGUID, fileRootPath, dataFilePath, infoFilePath);
|
||||
Result.Add(element);
|
||||
}
|
||||
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
return isFindItem;
|
||||
}
|
||||
private string FindDataFileExtension(DirectoryInfo directoryInfo)
|
||||
{
|
||||
string dataFileExtension = string.Empty;
|
||||
var fileInfos = directoryInfo.GetFiles();
|
||||
foreach (var fileInfo in fileInfos)
|
||||
{
|
||||
if (fileInfo.Name.StartsWith(DefaultCacheFileSystemDefine.BundleDataFileName))
|
||||
{
|
||||
dataFileExtension = fileInfo.Extension;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dataFileExtension;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8adb017a806563548b1d4c47f7b343e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存文件验证(线程版)
|
||||
/// </summary>
|
||||
internal sealed class VerifyCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly DefaultCacheFileSystem _fileSystem;
|
||||
private readonly EFileVerifyLevel _fileVerifyLevel;
|
||||
private List<VerifyFileElement> _waitingList;
|
||||
private List<VerifyFileElement> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private int _succeedCount;
|
||||
private int _failedCount;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal VerifyCacheFilesOperation(DefaultCacheFileSystem fileSystem, List<VerifyFileElement> elements)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_waitingList = elements;
|
||||
_fileVerifyLevel = fileSystem.FileVerifyLevel;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int fileCount = _waitingList.Count;
|
||||
|
||||
// 设置同时验证的最大数
|
||||
ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
|
||||
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
|
||||
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
|
||||
_verifyTotalCount = fileCount;
|
||||
if (_verifyMaxNum < 1)
|
||||
_verifyMaxNum = 1;
|
||||
|
||||
_verifyingList = new List<VerifyFileElement>(_verifyMaxNum);
|
||||
_steps = ESteps.UpdateVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerify)
|
||||
{
|
||||
// 检测校验结果
|
||||
for (int i = _verifyingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var verifyElement = _verifyingList[i];
|
||||
int result = verifyElement.Result;
|
||||
if (result != 0)
|
||||
{
|
||||
_verifyingList.RemoveAt(i);
|
||||
RecordVerifyFile(verifyElement);
|
||||
}
|
||||
}
|
||||
|
||||
Progress = GetProgress();
|
||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Verify cache files elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
|
||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
|
||||
if (_verifyingList.Count >= _verifyMaxNum)
|
||||
break;
|
||||
|
||||
var element = _waitingList[i];
|
||||
bool succeed = ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
||||
if (succeed)
|
||||
{
|
||||
_waitingList.RemoveAt(i);
|
||||
_verifyingList.Add(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning("The thread pool is failed queued.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetProgress()
|
||||
{
|
||||
if (_verifyTotalCount == 0)
|
||||
return 1f;
|
||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
||||
}
|
||||
private void VerifyInThread(object obj)
|
||||
{
|
||||
VerifyFileElement element = (VerifyFileElement)obj;
|
||||
int verifyResult = (int)VerifyingCacheFile(element, _fileVerifyLevel);
|
||||
element.Result = verifyResult;
|
||||
}
|
||||
private void RecordVerifyFile(VerifyFileElement element)
|
||||
{
|
||||
if (element.Result == (int)EFileVerifyResult.Succeed)
|
||||
{
|
||||
_succeedCount++;
|
||||
var recordFileElement = new RecordFileElement(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
||||
_fileSystem.RecordBundleFile(element.BundleGUID, recordFileElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCount++;
|
||||
YooLogger.Warning($"Failed to verify file {element.Result} and delete files : {element.FileRootPath}");
|
||||
element.DeleteFiles();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证缓存文件(子线程内操作)
|
||||
/// </summary>
|
||||
private EFileVerifyResult VerifyingCacheFile(VerifyFileElement element, EFileVerifyLevel verifyLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (verifyLevel == EFileVerifyLevel.Low)
|
||||
{
|
||||
if (File.Exists(element.InfoFilePath) == false)
|
||||
return EFileVerifyResult.InfoFileNotExisted;
|
||||
if (File.Exists(element.DataFilePath) == false)
|
||||
return EFileVerifyResult.DataFileNotExisted;
|
||||
return EFileVerifyResult.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(element.InfoFilePath) == false)
|
||||
return EFileVerifyResult.InfoFileNotExisted;
|
||||
|
||||
// 解析信息文件获取验证数据
|
||||
_fileSystem.ReadBundleInfoFile(element.InfoFilePath, out element.DataFileCRC, out element.DataFileSize);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return EFileVerifyResult.Exception;
|
||||
}
|
||||
|
||||
return FileVerifyHelper.FileVerify(element.DataFilePath, element.DataFileSize, element.DataFileCRC, verifyLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e9325baa24ae234ea0208d70dd3347e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载文件验证(线程版)
|
||||
/// </summary>
|
||||
internal sealed class VerifyTempFileOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
VerifyFile,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly TempFileElement _element;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 验证结果
|
||||
/// </summary>
|
||||
public EFileVerifyResult VerifyResult { private set; get; }
|
||||
|
||||
|
||||
internal VerifyTempFileOperation(TempFileElement element)
|
||||
{
|
||||
_element = element;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.VerifyFile;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.VerifyFile)
|
||||
{
|
||||
bool succeed = ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), _element);
|
||||
if (succeed)
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
int result = _element.Result;
|
||||
if (result == 0)
|
||||
return;
|
||||
|
||||
VerifyResult = (EFileVerifyResult)result;
|
||||
if (VerifyResult == EFileVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed to verify file : {_element.TempFilePath} ! ErrorCode : {VerifyResult}";
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
//TODO 等待子线程验证文件完毕,该操作会挂起主线程
|
||||
InternalOnUpdate();
|
||||
if (IsDone)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyInThread(object obj)
|
||||
{
|
||||
TempFileElement element = (TempFileElement)obj;
|
||||
int result = (int)FileVerifyHelper.FileVerify(element.TempFilePath, element.TempFileSize, element.TempFileCRC, EFileVerifyLevel.High);
|
||||
element.Result = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 764ac4f47afd3be4a8d583578f51126d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user