Update runtime code

重写了文件解密流程。
pull/51/head
hevinci 2022-11-02 21:54:44 +08:00
parent 3e4761a60f
commit e8e69a2e86
12 changed files with 302 additions and 108 deletions

View File

@ -13,6 +13,8 @@ namespace YooAsset
None = 0, None = 0,
Download, Download,
CheckDownload, CheckDownload,
Unpack,
CheckUnpack,
LoadFile, LoadFile,
CheckLoadFile, CheckLoadFile,
Done, Done,
@ -22,8 +24,10 @@ namespace YooAsset
private string _fileLoadPath; private string _fileLoadPath;
private bool _isWaitForAsyncComplete = false; private bool _isWaitForAsyncComplete = false;
private bool _isShowWaitForAsyncError = false; private bool _isShowWaitForAsyncError = false;
private DownloaderBase _unpacker;
private DownloaderBase _downloader; private DownloaderBase _downloader;
private AssetBundleCreateRequest _createRequest; private AssetBundleCreateRequest _createRequest;
private FileStream _fileStream;
public AssetBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo) public AssetBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
@ -47,8 +51,22 @@ namespace YooAsset
} }
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
#if UNITY_ANDROID
EBundleLoadMethod loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
if (loadMethod == EBundleLoadMethod.LoadFromMemory || loadMethod == EBundleLoadMethod.LoadFromStream)
{
_steps = ESteps.Unpack;
_fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
}
else
{
_steps = ESteps.LoadFile;
_fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
}
#else
_steps = ESteps.LoadFile; _steps = ESteps.LoadFile;
_fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath; _fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
#endif
} }
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
@ -87,7 +105,34 @@ namespace YooAsset
} }
} }
// 3. 加载AssetBundle // 3. 内置文件解压
if (_steps == ESteps.Unpack)
{
int failedTryAgain = 1;
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(MainBundleInfo.Bundle);
_unpacker = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckUnpack;
}
// 4.检测内置文件解压结果
if (_steps == ESteps.CheckUnpack)
{
if (_unpacker.IsDone() == false)
return;
if (_unpacker.HasError())
{
_steps = ESteps.Done;
Status = EStatus.Failed;
LastError = _unpacker.GetLastError();
}
else
{
_steps = ESteps.LoadFile;
}
}
// 5. 加载AssetBundle
if (_steps == ESteps.LoadFile) if (_steps == ESteps.LoadFile)
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
@ -103,31 +148,63 @@ namespace YooAsset
#endif #endif
// Load assetBundle file // Load assetBundle file
if (MainBundleInfo.Bundle.IsEncrypted) var loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
{ if (loadMethod == EBundleLoadMethod.Normal)
if (Impl.DecryptionServices == null)
throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.Bundle.BundleName}");
DecryptionFileInfo fileInfo = new DecryptionFileInfo();
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
fileInfo.FileHash = MainBundleInfo.Bundle.FileHash;
ulong offset = Impl.DecryptionServices.GetFileOffset(fileInfo);
if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset);
else
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
}
else
{ {
if (_isWaitForAsyncComplete) if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath); CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath);
else else
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath); _createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
} }
else
{
if (Impl.DecryptionServices == null)
{
_steps = ESteps.Done;
Status = EStatus.Failed;
LastError = $"{nameof(IDecryptionServices)} is null : {MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError);
return;
}
DecryptFileInfo fileInfo = new DecryptFileInfo();
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
fileInfo.FilePath = _fileLoadPath;
if (loadMethod == EBundleLoadMethod.LoadFromFileOffset)
{
ulong offset = Impl.DecryptionServices.LoadFromFileOffset(fileInfo);
if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset);
else
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
}
else if (loadMethod == EBundleLoadMethod.LoadFromMemory)
{
byte[] fileData = Impl.DecryptionServices.LoadFromMemory(fileInfo);
if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromMemory(fileData);
else
_createRequest = AssetBundle.LoadFromMemoryAsync(fileData);
}
else if (loadMethod == EBundleLoadMethod.LoadFromStream)
{
_fileStream = Impl.DecryptionServices.LoadFromStream(fileInfo);
uint managedReadBufferSize = Impl.DecryptionServices.GetManagedReadBufferSize();
if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromStream(_fileStream, 0, managedReadBufferSize);
else
_createRequest = AssetBundle.LoadFromStreamAsync(_fileStream, 0, managedReadBufferSize);
}
else
{
throw new System.NotImplementedException();
}
}
_steps = ESteps.CheckLoadFile; _steps = ESteps.CheckLoadFile;
} }
// 4. 检测AssetBundle加载结果 // 6. 检测AssetBundle加载结果
if (_steps == ESteps.CheckLoadFile) if (_steps == ESteps.CheckLoadFile)
{ {
if (_createRequest != null) if (_createRequest != null)
@ -177,6 +254,21 @@ namespace YooAsset
} }
} }
/// <summary>
/// 销毁
/// </summary>
public override void Destroy(bool forceDestroy)
{
base.Destroy(forceDestroy);
if (_fileStream != null)
{
_fileStream.Close();
_fileStream.Dispose();
_fileStream = null;
}
}
/// <summary> /// <summary>
/// 主线程等待异步操作完毕 /// 主线程等待异步操作完毕
/// </summary> /// </summary>

View File

@ -89,7 +89,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 销毁 /// 销毁
/// </summary> /// </summary>
public void Destroy(bool forceDestroy) public virtual void Destroy(bool forceDestroy)
{ {
IsDestroyed = true; IsDestroyed = true;

View File

@ -17,7 +17,7 @@ namespace YooAsset
LoadCacheFile, LoadCacheFile,
CheckLoadCacheFile, CheckLoadCacheFile,
LoadWebFile, LoadWebFile,
CheckLoadWebFile, CheckLoadWebFile,
TryLoadWebFile, TryLoadWebFile,
Done, Done,
} }
@ -30,7 +30,7 @@ namespace YooAsset
private UnityWebRequest _webRequest; private UnityWebRequest _webRequest;
private AssetBundleCreateRequest _createRequest; private AssetBundleCreateRequest _createRequest;
public AssetBundleWebLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo) public AssetBundleWebLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
{ {
} }
@ -108,20 +108,18 @@ namespace YooAsset
#endif #endif
// Load assetBundle file // Load assetBundle file
if (MainBundleInfo.Bundle.IsEncrypted) var loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
if (loadMethod == EBundleLoadMethod.Normal)
{ {
if (Impl.DecryptionServices == null) _createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.Bundle.BundleName}");
DecryptionFileInfo fileInfo = new DecryptionFileInfo();
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
fileInfo.FileHash = MainBundleInfo.Bundle.FileHash;
ulong offset = Impl.DecryptionServices.GetFileOffset(fileInfo);
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
} }
else else
{ {
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath); _steps = ESteps.Done;
Status = EStatus.Failed;
LastError = $"WebGL not support encrypted bundle file : {MainBundleInfo.Bundle.BundleName}";
YooLogger.Error(LastError);
return;
} }
_steps = ESteps.CheckLoadCacheFile; _steps = ESteps.CheckLoadCacheFile;
} }

View File

@ -0,0 +1,29 @@

namespace YooAsset
{
/// <summary>
/// Bundle文件的加载方法
/// </summary>
public enum EBundleLoadMethod
{
/// <summary>
/// 正常加载(不需要解密)
/// </summary>
Normal = 0,
/// <summary>
/// 通过文件偏移来解密加载
/// </summary>
LoadFromFileOffset = 1,
/// <summary>
/// 通过文件内存来解密加载
/// </summary>
LoadFromMemory = 2,
/// <summary>
/// 通过文件流来解密加载
/// </summary>
LoadFromStream = 3,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e32c14ed62806b4189d20ad48ce7631
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -171,14 +171,14 @@ namespace YooAsset
{ {
None, None,
Prepare, Prepare,
DownloadBuildinFile, Unpack,
CheckDownload, CheckUnpack,
CheckAndCopyFile, CheckAndCopyFile,
Done, Done,
} }
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private DownloaderBase _downloader; private DownloaderBase _unpacker;
public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath) public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{ {
@ -203,7 +203,7 @@ namespace YooAsset
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
_steps = ESteps.DownloadBuildinFile; _steps = ESteps.Unpack;
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
@ -215,27 +215,27 @@ namespace YooAsset
} }
} }
// 2. 下载文件 // 2. 内置文件解压
if (_steps == ESteps.DownloadBuildinFile) if (_steps == ESteps.Unpack)
{ {
int failedTryAgain = int.MaxValue; int failedTryAgain = 1;
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle); var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle);
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain); _unpacker = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload; _steps = ESteps.CheckUnpack;
} }
// 3. 检测下载结果 // 3. 检测内置文件解压结果
if (_steps == ESteps.CheckDownload) if (_steps == ESteps.CheckUnpack)
{ {
Progress = _downloader.DownloadProgress; Progress = _unpacker.DownloadProgress;
if (_downloader.IsDone() == false) if (_unpacker.IsDone() == false)
return; return;
if (_downloader.HasError()) if (_unpacker.HasError())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = _downloader.GetLastError(); Error = _unpacker.GetLastError();
} }
else else
{ {
@ -306,14 +306,16 @@ namespace YooAsset
{ {
None, None,
Prepare, Prepare,
DownloadWebFile, Download,
DownloadBuildinFile,
CheckDownload, CheckDownload,
Unpack,
CheckUnpack,
CheckAndCopyFile, CheckAndCopyFile,
Done, Done,
} }
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private DownloaderBase _unpacker;
private DownloaderBase _downloader; private DownloaderBase _downloader;
internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath) internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
@ -339,11 +341,11 @@ namespace YooAsset
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
{ {
_steps = ESteps.DownloadWebFile; _steps = ESteps.Download;
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{ {
_steps = ESteps.DownloadBuildinFile; _steps = ESteps.Unpack;
} }
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache) else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{ {
@ -356,23 +358,14 @@ namespace YooAsset
} }
// 2. 下载远端文件 // 2. 下载远端文件
if (_steps == ESteps.DownloadWebFile) if (_steps == ESteps.Download)
{ {
int failedTryAgain = int.MaxValue; int failedTryAgain = int.MaxValue;
_downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain); _downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload; _steps = ESteps.CheckDownload;
} }
// 3. 下载内置文件 // 3. 检测下载结果
if (_steps == ESteps.DownloadBuildinFile)
{
int failedTryAgain = int.MaxValue;
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle);
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload;
}
// 4. 检测下载结果
if (_steps == ESteps.CheckDownload) if (_steps == ESteps.CheckDownload)
{ {
Progress = _downloader.DownloadProgress; Progress = _downloader.DownloadProgress;
@ -391,6 +384,34 @@ namespace YooAsset
} }
} }
// 3. 解压内置文件
if (_steps == ESteps.Unpack)
{
int failedTryAgain = 1;
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle);
_unpacker = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckUnpack;
}
// 4. 检测解压结果
if (_steps == ESteps.CheckUnpack)
{
Progress = _unpacker.DownloadProgress;
if (_unpacker.IsDone() == false)
return;
if (_unpacker.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unpacker.GetLastError();
}
else
{
_steps = ESteps.CheckAndCopyFile;
}
}
// 5. 检测并拷贝原生文件 // 5. 检测并拷贝原生文件
if (_steps == ESteps.CheckAndCopyFile) if (_steps == ESteps.CheckAndCopyFile)
{ {

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Linq; using System.Linq;
using System.IO;
namespace YooAsset namespace YooAsset
{ {
@ -27,27 +26,21 @@ namespace YooAsset
/// </summary> /// </summary>
public long FileSize; public long FileSize;
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile;
/// <summary>
/// 加载方法
/// </summary>
public byte LoadMethod;
/// <summary> /// <summary>
/// 资源包的分类标签 /// 资源包的分类标签
/// </summary> /// </summary>
public string[] Tags; public string[] Tags;
/// <summary>
/// Flags
/// </summary>
public int Flags;
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile { private set; get; }
/// <summary>
/// 是否为加密文件
/// </summary>
public bool IsEncrypted { private set; get; }
/// <summary> /// <summary>
/// 文件名称 /// 文件名称
/// </summary> /// </summary>
@ -87,37 +80,15 @@ namespace YooAsset
} }
public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, string[] tags) public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, bool isRawFile, byte loadMethod, string[] tags)
{ {
BundleName = bundleName; BundleName = bundleName;
FileHash = fileHash; FileHash = fileHash;
FileCRC = fileCRC; FileCRC = fileCRC;
FileSize = fileSize; FileSize = fileSize;
Tags = tags;
}
/// <summary>
/// 设置Flags
/// </summary>
public void SetFlagsValue(bool isRawFile, bool isEncrypted)
{
IsRawFile = isRawFile; IsRawFile = isRawFile;
IsEncrypted = isEncrypted; LoadMethod = loadMethod;
Tags = tags;
BitMask32 mask = new BitMask32(0);
if (isRawFile) mask.Open(0);
if (isEncrypted) mask.Open(1);
Flags = mask;
}
/// <summary>
/// 解析Flags
/// </summary>
public void ParseFlagsValue()
{
BitMask32 value = Flags;
IsRawFile = value.Test(0);
IsEncrypted = value.Test(1);
} }
/// <summary> /// <summary>

View File

@ -290,7 +290,6 @@ namespace YooAsset
// BundleList // BundleList
foreach (var patchBundle in patchManifest.BundleList) foreach (var patchBundle in patchManifest.BundleList)
{ {
patchBundle.ParseFlagsValue();
patchBundle.ParseFileName(patchManifest.OutputNameStyle); patchBundle.ParseFileName(patchManifest.OutputNameStyle);
patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle); patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle);
} }

View File

@ -1,17 +1,42 @@
 
namespace YooAsset namespace YooAsset
{ {
public struct DecryptionFileInfo public struct DecryptFileInfo
{ {
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName; public string BundleName;
public string FileHash;
/// <summary>
/// 文件路径
/// </summary>
public string FilePath;
} }
/// <summary>
/// 解密类服务接口
/// </summary>
public interface IDecryptionServices public interface IDecryptionServices
{ {
/// <summary> /// <summary>
/// 获取加密文件的数据偏移量 /// 文件偏移解密方法
/// </summary> /// </summary>
ulong GetFileOffset(DecryptionFileInfo fileInfo); ulong LoadFromFileOffset(DecryptFileInfo fileInfo);
/// <summary>
/// 文件内存解密方法
/// </summary>
byte[] LoadFromMemory(DecryptFileInfo fileInfo);
/// <summary>
/// 文件流解密方法
/// </summary>
System.IO.FileStream LoadFromStream(DecryptFileInfo fileInfo);
/// <summary>
/// 文件流解密的托管缓存大小
/// </summary>
uint GetManagedReadBufferSize();
} }
} }

View File

@ -0,0 +1,37 @@

namespace YooAsset
{
public struct EncryptResult
{
/// <summary>
/// 加密后的Bunlde文件加载方法
/// </summary>
public EBundleLoadMethod LoadMethod;
/// <summary>
/// 加密后的文件数据
/// </summary>
public byte[] EncryptedData;
}
public struct EncryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 文件路径
/// </summary>
public string FilePath;
}
/// <summary>
/// 加密服务类接口
/// </summary>
public interface IEncryptionServices
{
EncryptResult Encrypt(EncryptFileInfo fileInfo);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04491137351983348959c00ec4ee226a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -24,7 +24,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 补丁清单文件格式版本 /// 补丁清单文件格式版本
/// </summary> /// </summary>
public const string PatchManifestFileVersion = "1.3.3"; public const string PatchManifestFileVersion = "1.3.4";
/// <summary> /// <summary>
/// 构建输出文件夹名称 /// 构建输出文件夹名称