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,
Download,
CheckDownload,
Unpack,
CheckUnpack,
LoadFile,
CheckLoadFile,
Done,
@ -22,8 +24,10 @@ namespace YooAsset
private string _fileLoadPath;
private bool _isWaitForAsyncComplete = false;
private bool _isShowWaitForAsyncError = false;
private DownloaderBase _unpacker;
private DownloaderBase _downloader;
private AssetBundleCreateRequest _createRequest;
private FileStream _fileStream;
public AssetBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
@ -47,9 +51,23 @@ namespace YooAsset
}
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;
_fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
#endif
}
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
{
_steps = ESteps.LoadFile;
@ -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 UNITY_EDITOR
@ -103,31 +148,63 @@ namespace YooAsset
#endif
// Load assetBundle file
if (MainBundleInfo.Bundle.IsEncrypted)
{
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
var loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
if (loadMethod == EBundleLoadMethod.Normal)
{
if (_isWaitForAsyncComplete)
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath);
else
_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;
}
// 4. 检测AssetBundle加载结果
// 6. 检测AssetBundle加载结果
if (_steps == ESteps.CheckLoadFile)
{
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>

View File

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

View File

@ -108,20 +108,18 @@ namespace YooAsset
#endif
// 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);
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
}
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;
}

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

View File

@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.IO;
namespace YooAsset
{
@ -27,27 +26,21 @@ namespace YooAsset
/// </summary>
public long FileSize;
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile;
/// <summary>
/// 加载方法
/// </summary>
public byte LoadMethod;
/// <summary>
/// 资源包的分类标签
/// </summary>
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>
@ -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;
FileHash = fileHash;
FileCRC = fileCRC;
FileSize = fileSize;
Tags = tags;
}
/// <summary>
/// 设置Flags
/// </summary>
public void SetFlagsValue(bool isRawFile, bool isEncrypted)
{
IsRawFile = isRawFile;
IsEncrypted = isEncrypted;
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);
LoadMethod = loadMethod;
Tags = tags;
}
/// <summary>

View File

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

View File

@ -1,17 +1,42 @@

namespace YooAsset
{
public struct DecryptionFileInfo
public struct DecryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
public string FileHash;
/// <summary>
/// 文件路径
/// </summary>
public string FilePath;
}
/// <summary>
/// 解密类服务接口
/// </summary>
public interface IDecryptionServices
{
/// <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>
public const string PatchManifestFileVersion = "1.3.3";
public const string PatchManifestFileVersion = "1.3.4";
/// <summary>
/// 构建输出文件夹名称