Update runtime code

AssetsPackage.WeaklyUpdateManifestAsync(string packageVersion)移除了packageVersion参数。
优化了HostPlayMode的初始化逻辑,优先读取沙盒内的清单,如果不存在则读取内置清单。
pull/51/head
hevinci 2022-10-31 16:45:21 +08:00
parent 171f40551e
commit cd79f0e434
14 changed files with 341 additions and 225 deletions

View File

@ -219,7 +219,7 @@ namespace YooAsset
if (_steps == ESteps.DownloadBuildinFile) if (_steps == ESteps.DownloadBuildinFile)
{ {
int failedTryAgain = int.MaxValue; int failedTryAgain = int.MaxValue;
var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle); var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle);
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain); _downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload; _steps = ESteps.CheckDownload;
} }
@ -367,7 +367,7 @@ namespace YooAsset
if (_steps == ESteps.DownloadBuildinFile) if (_steps == ESteps.DownloadBuildinFile)
{ {
int failedTryAgain = int.MaxValue; int failedTryAgain = int.MaxValue;
var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle); var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(_bundleInfo.Bundle);
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain); _downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
_steps = ESteps.CheckDownload; _steps = ESteps.CheckDownload;
} }

View File

@ -182,7 +182,7 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 向网络端请求静态资源版本 /// 向网络端请求最新的资源版本
/// </summary> /// </summary>
/// <param name="timeout">超时时间默认值60秒</param> /// <param name="timeout">超时时间默认值60秒</param>
public UpdateStaticVersionOperation UpdateStaticVersionAsync(int timeout = 60) public UpdateStaticVersionOperation UpdateStaticVersionAsync(int timeout = 60)
@ -242,11 +242,10 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 弱联网情况下加载补丁清单 /// 弱联网情况下加载本地的补丁清单
/// 注意:当指定版本内容验证失败后会返回失败。 /// 注意:当清单里的内容验证失败后会返回失败。
/// </summary> /// </summary>
/// <param name="packageVersion">指定的包裹版本</param> public UpdateManifestOperation WeaklyUpdateManifestAsync()
public UpdateManifestOperation WeaklyUpdateManifestAsync(string packageVersion)
{ {
DebugCheckInitialize(); DebugCheckInitialize();
if (_playMode == EPlayMode.EditorSimulateMode) if (_playMode == EPlayMode.EditorSimulateMode)
@ -263,7 +262,7 @@ namespace YooAsset
} }
else if (_playMode == EPlayMode.HostPlayMode) else if (_playMode == EPlayMode.HostPlayMode)
{ {
return _hostPlayModeImpl.WeaklyUpdatePatchManifestAsync(PackageName, packageVersion); return _hostPlayModeImpl.WeaklyUpdatePatchManifestAsync(PackageName);
} }
else else
{ {
@ -945,9 +944,9 @@ namespace YooAsset
private void DebugCheckInitialize() private void DebugCheckInitialize()
{ {
if (_initializeStatus == EOperationStatus.None) if (_initializeStatus == EOperationStatus.None)
throw new Exception("YooAssets initialize not completed !"); throw new Exception("Package initialize not completed !");
else if (_initializeStatus == EOperationStatus.Failed) else if (_initializeStatus == EOperationStatus.Failed)
throw new Exception($"YooAssets initialize failed : {_initializeError}"); throw new Exception($"Package initialize failed ! {_initializeError}");
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]

View File

@ -84,7 +84,7 @@ namespace YooAsset
/// </summary> /// </summary>
private List<string> GetUnusedCacheFilePaths() private List<string> GetUnusedCacheFilePaths()
{ {
string cacheFolderPath = SandboxHelper.GetCacheFolderPath(); string cacheFolderPath = PersistentHelper.GetCacheFolderPath();
if (Directory.Exists(cacheFolderPath) == false) if (Directory.Exists(cacheFolderPath) == false)
return new List<string>(); return new List<string>();

View File

@ -25,7 +25,7 @@ namespace YooAsset
} }
private readonly EditorSimulateModeImpl _impl; private readonly EditorSimulateModeImpl _impl;
private string _simulatePatchManifestPath; private readonly string _simulatePatchManifestPath;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal EditorSimulateModeInitializationOperation(EditorSimulateModeImpl impl, string simulatePatchManifestPath) internal EditorSimulateModeInitializationOperation(EditorSimulateModeImpl impl, string simulatePatchManifestPath)
@ -45,16 +45,25 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"Manifest file not found : {_simulatePatchManifestPath}"; Error = $"Not found simulation manifest file : {_simulatePatchManifestPath}";
return; return;
} }
YooLogger.Log($"Load manifest file : {_simulatePatchManifestPath}"); try
string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath); {
var simulatePatchManifest = PatchManifest.Deserialize(jsonContent); YooLogger.Log($"Load simulation manifest file : {_simulatePatchManifestPath}");
_impl.SetSimulatePatchManifest(simulatePatchManifest); string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath);
_steps = ESteps.Done; var manifest = PatchManifest.Deserialize(jsonContent);
Status = EOperationStatus.Succeed; _impl.SetSimulatePatchManifest(manifest);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (System.Exception e)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = e.Message;
}
} }
} }
} }
@ -67,7 +76,7 @@ namespace YooAsset
private enum ESteps private enum ESteps
{ {
None, None,
QueryPackageVersion, QueryAppPackageVersion,
LoadAppManifest, LoadAppManifest,
InitVerifyingCache, InitVerifyingCache,
UpdateVerifyingCache, UpdateVerifyingCache,
@ -76,7 +85,7 @@ namespace YooAsset
private readonly OfflinePlayModeImpl _impl; private readonly OfflinePlayModeImpl _impl;
private readonly string _packageName; private readonly string _packageName;
private readonly CacheVerifier _patchCacheVerifier; private readonly CacheVerifier _cacheVerifier;
private readonly AppPackageVersionQuerier _appPackageVersionQuerier; private readonly AppPackageVersionQuerier _appPackageVersionQuerier;
private AppManifestLoader _appManifestLoader; private AppManifestLoader _appManifestLoader;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
@ -89,21 +98,21 @@ namespace YooAsset
_appPackageVersionQuerier = new AppPackageVersionQuerier(packageName); _appPackageVersionQuerier = new AppPackageVersionQuerier(packageName);
#if UNITY_WEBGL #if UNITY_WEBGL
_patchCacheVerifier = new CacheVerifierWithoutThread(); _cacheVerifier = new CacheVerifierWithoutThread();
#else #else
_patchCacheVerifier = new CacheVerifierWithThread(); _cacheVerifier = new CacheVerifierWithThread();
#endif #endif
} }
internal override void Start() internal override void Start()
{ {
_steps = ESteps.QueryPackageVersion; _steps = ESteps.QueryAppPackageVersion;
} }
internal override void Update() internal override void Update()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.QueryPackageVersion) if (_steps == ESteps.QueryAppPackageVersion)
{ {
_appPackageVersionQuerier.Update(); _appPackageVersionQuerier.Update();
if (_appPackageVersionQuerier.IsDone == false) if (_appPackageVersionQuerier.IsDone == false)
@ -130,7 +139,8 @@ namespace YooAsset
if (_appManifestLoader.IsDone == false) if (_appManifestLoader.IsDone == false)
return; return;
if (_appManifestLoader.Manifest == null) var manifest = _appManifestLoader.Manifest;
if (manifest == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
@ -139,27 +149,27 @@ namespace YooAsset
else else
{ {
_steps = ESteps.InitVerifyingCache; _steps = ESteps.InitVerifyingCache;
_impl.SetAppPatchManifest(_appManifestLoader.Manifest); _impl.SetAppPatchManifest(manifest);
} }
} }
if (_steps == ESteps.InitVerifyingCache) if (_steps == ESteps.InitVerifyingCache)
{ {
var verifyInfos = _impl.GetVerifyInfoList(); var verifyInfos = _impl.GetVerifyInfoList();
_patchCacheVerifier.InitVerifier(verifyInfos); _cacheVerifier.InitVerifier(verifyInfos);
_verifyTime = UnityEngine.Time.realtimeSinceStartup; _verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache; _steps = ESteps.UpdateVerifyingCache;
} }
if (_steps == ESteps.UpdateVerifyingCache) if (_steps == ESteps.UpdateVerifyingCache)
{ {
Progress = _patchCacheVerifier.GetVerifierProgress(); Progress = _cacheVerifier.GetVerifierProgress();
if (_patchCacheVerifier.UpdateVerifier()) if (_cacheVerifier.UpdateVerifier())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime; float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessList.Count}, Fail {_patchCacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds"); YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
} }
} }
} }
@ -167,15 +177,17 @@ namespace YooAsset
/// <summary> /// <summary>
/// 联机运行模式的初始化操作 /// 联机运行模式的初始化操作
/// 注意:优先从沙盒里加载清单,如果沙盒里不存在就尝试把内置清单拷贝到沙盒并加载该清单。
/// </summary> /// </summary>
internal sealed class HostPlayModeInitializationOperation : InitializationOperation internal sealed class HostPlayModeInitializationOperation : InitializationOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
QueryPackageVersion, TryLoadCacheManifest,
LoadAppManifest, QueryAppPackageVersion,
CopyAppManifest, CopyAppManifest,
LoadAppManifest,
InitVerifyingCache, InitVerifyingCache,
UpdateVerifyingCache, UpdateVerifyingCache,
Done, Done,
@ -183,7 +195,7 @@ namespace YooAsset
private readonly HostPlayModeImpl _impl; private readonly HostPlayModeImpl _impl;
private readonly string _packageName; private readonly string _packageName;
private readonly CacheVerifier _patchCacheVerifier; private readonly CacheVerifier _cacheVerifier;
private readonly AppPackageVersionQuerier _appPackageVersionQuerier; private readonly AppPackageVersionQuerier _appPackageVersionQuerier;
private AppManifestCopyer _appManifestCopyer; private AppManifestCopyer _appManifestCopyer;
private AppManifestLoader _appManifestLoader; private AppManifestLoader _appManifestLoader;
@ -197,21 +209,45 @@ namespace YooAsset
_appPackageVersionQuerier = new AppPackageVersionQuerier(packageName); _appPackageVersionQuerier = new AppPackageVersionQuerier(packageName);
#if UNITY_WEBGL #if UNITY_WEBGL
_patchCacheVerifier = new CacheVerifierWithoutThread(); _cacheVerifier = new CacheVerifierWithoutThread();
#else #else
_patchCacheVerifier = new CacheVerifierWithThread(); _cacheVerifier = new CacheVerifierWithThread();
#endif #endif
} }
internal override void Start() internal override void Start()
{ {
_steps = ESteps.QueryPackageVersion; _steps = ESteps.TryLoadCacheManifest;
} }
internal override void Update() internal override void Update()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.QueryPackageVersion) if (_steps == ESteps.TryLoadCacheManifest)
{
if (PersistentHelper.CheckCacheManifestFileExists(_packageName))
{
try
{
var manifest = PersistentHelper.LoadCacheManifestFile(_packageName);
_impl.SetLocalPatchManifest(manifest);
_steps = ESteps.InitVerifyingCache;
}
catch (System.Exception e)
{
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,我们主动把损坏的文件删除。
YooLogger.Warning($"Failed to load cache manifest file : {e.Message}");
PersistentHelper.DeleteCacheManifestFile(_packageName);
_steps = ESteps.QueryAppPackageVersion;
}
}
else
{
_steps = ESteps.QueryAppPackageVersion;
}
}
if (_steps == ESteps.QueryAppPackageVersion)
{ {
_appPackageVersionQuerier.Update(); _appPackageVersionQuerier.Update();
if (_appPackageVersionQuerier.IsDone == false) if (_appPackageVersionQuerier.IsDone == false)
@ -223,6 +259,7 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
YooLogger.Log($"Failed to load buildin package version file : {error}");
} }
else else
{ {
@ -240,7 +277,7 @@ namespace YooAsset
return; return;
string error = _appManifestCopyer.Error; string error = _appManifestCopyer.Error;
if(string.IsNullOrEmpty(error) == false) if (string.IsNullOrEmpty(error) == false)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
@ -259,7 +296,8 @@ namespace YooAsset
if (_appManifestLoader.IsDone == false) if (_appManifestLoader.IsDone == false)
return; return;
if (_appManifestLoader.Manifest == null) var manifest = _appManifestLoader.Manifest;
if (manifest == null)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
@ -267,35 +305,37 @@ namespace YooAsset
} }
else else
{ {
_impl.SetLocalPatchManifest(manifest);
_steps = ESteps.InitVerifyingCache; _steps = ESteps.InitVerifyingCache;
_impl.SetLocalPatchManifest(_appManifestLoader.Manifest);
} }
} }
if (_steps == ESteps.InitVerifyingCache) if (_steps == ESteps.InitVerifyingCache)
{ {
var verifyInfos = _impl.GetVerifyInfoList(false); var verifyInfos = _impl.GetVerifyInfoList(false);
_patchCacheVerifier.InitVerifier(verifyInfos); _cacheVerifier.InitVerifier(verifyInfos);
_verifyTime = UnityEngine.Time.realtimeSinceStartup; _verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache; _steps = ESteps.UpdateVerifyingCache;
} }
if (_steps == ESteps.UpdateVerifyingCache) if (_steps == ESteps.UpdateVerifyingCache)
{ {
Progress = _patchCacheVerifier.GetVerifierProgress(); Progress = _cacheVerifier.GetVerifierProgress();
if (_patchCacheVerifier.UpdateVerifier()) if (_cacheVerifier.UpdateVerifier())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime; float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessList.Count}, Fail {_patchCacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds"); YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
} }
} }
} }
} }
// 内置补丁清单版本查询器 /// <summary>
/// 内置补丁清单版本查询器
/// </summary>
internal class AppPackageVersionQuerier internal class AppPackageVersionQuerier
{ {
private enum ESteps private enum ESteps
@ -367,7 +407,7 @@ namespace YooAsset
{ {
Version = _downloader.GetText(); Version = _downloader.GetText();
if (string.IsNullOrEmpty(Version)) if (string.IsNullOrEmpty(Version))
Error = $"Buildin package version is empty !"; Error = $"Buildin package version file content is empty !";
} }
_steps = ESteps.Done; _steps = ESteps.Done;
_downloader.Dispose(); _downloader.Dispose();
@ -375,7 +415,9 @@ namespace YooAsset
} }
} }
// 内置补丁清单加载器 /// <summary>
/// 内置补丁清单加载器
/// </summary>
internal class AppManifestLoader internal class AppManifestLoader
{ {
private enum ESteps private enum ESteps
@ -461,7 +503,14 @@ namespace YooAsset
else else
{ {
// 解析APP里的补丁清单 // 解析APP里的补丁清单
Manifest = PatchManifest.Deserialize(_downloader.GetText()); try
{
Manifest = PatchManifest.Deserialize(_downloader.GetText());
}
catch (System.Exception e)
{
Error = e.Message;
}
} }
_steps = ESteps.Done; _steps = ESteps.Done;
_downloader.Dispose(); _downloader.Dispose();
@ -469,7 +518,9 @@ namespace YooAsset
} }
} }
// 内置补丁清单复制器 /// <summary>
/// 内置补丁清单复制器
/// </summary>
internal class AppManifestCopyer internal class AppManifestCopyer
{ {
private enum ESteps private enum ESteps
@ -530,20 +581,13 @@ namespace YooAsset
if (_steps == ESteps.CopyAppManifest) if (_steps == ESteps.CopyAppManifest)
{ {
string savePath = PersistentHelper.GetCacheManifestFilePath(_buildinPackageName);
string fileName = YooAssetSettingsData.GetPatchManifestFileName(_buildinPackageName, _buildinPackageVersion); string fileName = YooAssetSettingsData.GetPatchManifestFileName(_buildinPackageName, _buildinPackageVersion);
string destFilePath = PathHelper.MakePersistentLoadPath(fileName); string filePath = PathHelper.MakeStreamingLoadPath(fileName);
if (File.Exists(destFilePath)) string url = PathHelper.ConvertToWWWPath(filePath);
{ _downloader = new UnityWebFileRequester();
_steps = ESteps.Done; _downloader.SendRequest(url, savePath);
} _steps = ESteps.CheckAppManifest;
else
{
string sourceFilePath = PathHelper.MakeStreamingLoadPath(fileName);
string url = PathHelper.ConvertToWWWPath(sourceFilePath);
_downloader = new UnityWebFileRequester();
_downloader.SendRequest(url, destFilePath);
_steps = ESteps.CheckAppManifest;
}
} }
if (_steps == ESteps.CheckAppManifest) if (_steps == ESteps.CheckAppManifest)

View File

@ -13,7 +13,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// 是否发现了新的补丁清单 /// 是否发现了新的补丁清单
/// </summary> /// </summary>
public bool FoundNewManifest { protected set; get; } public bool FoundNewManifest { protected set; get; } = false;
} }
/// <summary> /// <summary>
@ -46,14 +46,17 @@ namespace YooAsset
/// <summary> /// <summary>
/// 联机模式的更新清单操作 /// 联机模式的更新清单操作
/// 注意:优先比对沙盒清单哈希值,如果有变化就更新远端清单文件,并保存到本地。
/// </summary> /// </summary>
internal sealed class HostPlayModeUpdateManifestOperation : UpdateManifestOperation internal sealed class HostPlayModeUpdateManifestOperation : UpdateManifestOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
TryLoadCacheHash,
LoadWebHash, LoadWebHash,
CheckWebHash, CheckWebHash,
LoadCacheManifest,
LoadWebManifest, LoadWebManifest,
CheckWebManifest, CheckWebManifest,
InitVerifyingCache, InitVerifyingCache,
@ -65,10 +68,12 @@ namespace YooAsset
private readonly HostPlayModeImpl _impl; private readonly HostPlayModeImpl _impl;
private readonly string _packageName; private readonly string _packageName;
private readonly string _packageVersion; private readonly string _packageVersion;
private readonly CacheVerifier _cacheVerifier;
private readonly int _timeout; private readonly int _timeout;
private UnityWebDataRequester _downloader1; private UnityWebDataRequester _downloader1;
private UnityWebDataRequester _downloader2; private UnityWebDataRequester _downloader2;
private CacheVerifier _cacheVerifier;
private string _cacheManifestHash;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private float _verifyTime; private float _verifyTime;
@ -88,13 +93,27 @@ namespace YooAsset
internal override void Start() internal override void Start()
{ {
RequestCount++; RequestCount++;
_steps = ESteps.LoadWebHash; _steps = ESteps.TryLoadCacheHash;
} }
internal override void Update() internal override void Update()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.TryLoadCacheHash)
{
string filePath = PersistentHelper.GetCacheManifestFilePath(_packageName);
if (File.Exists(filePath))
{
_cacheManifestHash = HashUtility.FileMD5(filePath);
_steps = ESteps.LoadWebHash;
}
else
{
_steps = ESteps.LoadWebManifest;
}
}
if (_steps == ESteps.LoadWebHash) if (_steps == ESteps.LoadWebHash)
{ {
string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(_packageName, _packageVersion); string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(_packageName, _packageVersion);
@ -110,7 +129,6 @@ namespace YooAsset
if (_downloader1.IsDone() == false) if (_downloader1.IsDone() == false)
return; return;
// Check error
if (_downloader1.HasError()) if (_downloader1.HasError())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
@ -120,26 +138,37 @@ namespace YooAsset
else else
{ {
string webManifestHash = _downloader1.GetText(); string webManifestHash = _downloader1.GetText();
string cachedManifestHash = GetSandboxPatchManifestFileHash(_packageName, _packageVersion); if (_cacheManifestHash == webManifestHash)
// 如果补丁清单文件的哈希值相同
if (cachedManifestHash == webManifestHash)
{ {
YooLogger.Log($"Patch manifest file hash is not change : {webManifestHash}"); YooLogger.Log($"Not found new package : {_packageName}");
LoadSandboxPatchManifest(_packageName, _packageVersion); _steps = ESteps.LoadCacheManifest;
FoundNewManifest = false;
_steps = ESteps.InitVerifyingCache;
} }
else else
{ {
YooLogger.Log($"Patch manifest hash is change : {cachedManifestHash} -> {webManifestHash}"); YooLogger.Log($"Package {_packageName} is change : {_cacheManifestHash} -> {webManifestHash}");
FoundNewManifest = true;
_steps = ESteps.LoadWebManifest; _steps = ESteps.LoadWebManifest;
} }
} }
_downloader1.Dispose(); _downloader1.Dispose();
} }
if (_steps == ESteps.LoadCacheManifest)
{
try
{
var manifest = PersistentHelper.LoadCacheManifestFile(_packageName);
_impl.SetLocalPatchManifest(manifest);
_steps = ESteps.InitVerifyingCache;
}
catch (System.Exception e)
{
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,我们主动把损坏的文件删除。
YooLogger.Warning($"Failed to load cache manifest file : {e.Message}");
PersistentHelper.DeleteCacheManifestFile(_packageName);
_steps = ESteps.LoadWebManifest;
}
}
if (_steps == ESteps.LoadWebManifest) if (_steps == ESteps.LoadWebManifest)
{ {
string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion); string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion);
@ -155,7 +184,6 @@ namespace YooAsset
if (_downloader2.IsDone() == false) if (_downloader2.IsDone() == false)
return; return;
// Check error
if (_downloader2.HasError()) if (_downloader2.HasError())
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
@ -164,16 +192,19 @@ namespace YooAsset
} }
else else
{ {
// 解析补丁清单 try
if (ParseAndSaveRemotePatchManifest(_packageName, _packageVersion, _downloader2.GetText()))
{ {
string content = _downloader2.GetText();
var manifest = PersistentHelper.SaveCacheManifestFile(_packageName, content);
_impl.SetLocalPatchManifest(manifest);
FoundNewManifest = true;
_steps = ESteps.InitVerifyingCache; _steps = ESteps.InitVerifyingCache;
} }
else catch (Exception e)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"URL : {_downloader2.URL} Error : remote patch manifest content is invalid"; Error = e.Message;
} }
} }
_downloader2.Dispose(); _downloader2.Dispose();
@ -211,68 +242,20 @@ namespace YooAsset
else else
return _impl.GetPatchDownloadMainURL(fileName); return _impl.GetPatchDownloadMainURL(fileName);
} }
/// <summary>
/// 解析并保存远端请求的补丁清单
/// </summary>
private bool ParseAndSaveRemotePatchManifest(string packageName, string packageVersion, string content)
{
try
{
var remotePatchManifest = PatchManifest.Deserialize(content);
_impl.SetLocalPatchManifest(remotePatchManifest);
YooLogger.Log("Save remote patch manifest file.");
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
string savePath = PathHelper.MakePersistentLoadPath(fileName);
PatchManifest.Serialize(savePath, remotePatchManifest);
return true;
}
catch (Exception e)
{
YooLogger.Error(e.ToString());
return false;
}
}
/// <summary>
/// 加载沙盒内的补丁清单
/// 注意:在加载本地补丁清单之前,已经验证过文件的哈希值
/// </summary>
private void LoadSandboxPatchManifest(string packageName, string packageVersion)
{
YooLogger.Log("Load sandbox patch manifest file.");
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
string filePath = PathHelper.MakePersistentLoadPath(fileName);
string jsonData = File.ReadAllText(filePath);
var sandboxPatchManifest = PatchManifest.Deserialize(jsonData);
_impl.SetLocalPatchManifest(sandboxPatchManifest);
}
/// <summary>
/// 获取沙盒内补丁清单文件的哈希值
/// 注意:如果沙盒内补丁清单文件不存在,返回空字符串
/// </summary>
private string GetSandboxPatchManifestFileHash(string packageName, string packageVersion)
{
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
string filePath = PathHelper.MakePersistentLoadPath(fileName);
if (File.Exists(filePath))
return HashUtility.FileMD5(filePath);
else
return string.Empty;
}
} }
/// <summary> /// <summary>
/// 联机模式的更新清单操作(弱联网) /// 联机模式的更新清单操作(弱联网)
/// 注意:优先加载沙盒内的清单文件,如果不存在或加载失败,然后加载内置清单。
/// </summary> /// </summary>
internal sealed class HostPlayModeWeaklyUpdateManifestOperation : UpdateManifestOperation internal sealed class HostPlayModeWeaklyUpdateManifestOperation : UpdateManifestOperation
{ {
private enum ESteps private enum ESteps
{ {
None, None,
LoadSandboxManifestHash, TryLoadSandboxManifest,
QueryAppPackageVersion,
LoadAppManifest,
InitVerifyingCache, InitVerifyingCache,
UpdateVerifyingCache, UpdateVerifyingCache,
Done, Done,
@ -280,16 +263,17 @@ namespace YooAsset
private readonly HostPlayModeImpl _impl; private readonly HostPlayModeImpl _impl;
private readonly string _packageName; private readonly string _packageName;
private readonly string _packageVersion; private readonly CacheVerifier _cacheVerifier;
private readonly AppPackageVersionQuerier _appPackageVersionQuerier;
private AppManifestLoader _appManifestLoader;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
private CacheVerifier _cacheVerifier;
private float _verifyTime; private float _verifyTime;
internal HostPlayModeWeaklyUpdateManifestOperation(HostPlayModeImpl impl, string packageName, string packageVersion) internal HostPlayModeWeaklyUpdateManifestOperation(HostPlayModeImpl impl, string packageName)
{ {
_impl = impl; _impl = impl;
_packageName = packageName; _packageName = packageName;
_packageVersion = packageVersion; _appPackageVersionQuerier = new AppPackageVersionQuerier(packageName);
#if UNITY_WEBGL #if UNITY_WEBGL
_cacheVerifier = new CacheVerifierWithoutThread(); _cacheVerifier = new CacheVerifierWithoutThread();
@ -299,17 +283,76 @@ namespace YooAsset
} }
internal override void Start() internal override void Start()
{ {
_steps = ESteps.LoadSandboxManifestHash; _steps = ESteps.TryLoadSandboxManifest;
} }
internal override void Update() internal override void Update()
{ {
if (_steps == ESteps.None || _steps == ESteps.Done) if (_steps == ESteps.None || _steps == ESteps.Done)
return; return;
if (_steps == ESteps.LoadSandboxManifestHash) if (_steps == ESteps.TryLoadSandboxManifest)
{ {
LoadSandboxPatchManifest(_packageName, _packageVersion); if (PersistentHelper.CheckCacheManifestFileExists(_packageName) == false)
_steps = ESteps.InitVerifyingCache; {
_steps = ESteps.QueryAppPackageVersion;
}
else
{
try
{
var manifest = PersistentHelper.LoadCacheManifestFile(_packageName);
_impl.SetLocalPatchManifest(manifest);
_steps = ESteps.InitVerifyingCache;
}
catch (System.Exception e)
{
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,我们主动把损坏的文件删除。
YooLogger.Warning($"Failed to load cache manifest file : {e.Message}");
PersistentHelper.DeleteCacheManifestFile(_packageName);
_steps = ESteps.QueryAppPackageVersion;
}
}
}
if (_steps == ESteps.QueryAppPackageVersion)
{
_appPackageVersionQuerier.Update();
if (_appPackageVersionQuerier.IsDone == false)
return;
string error = _appPackageVersionQuerier.Error;
if (string.IsNullOrEmpty(error) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = error;
}
else
{
_appManifestLoader = new AppManifestLoader(_packageName, _appPackageVersionQuerier.Version);
_steps = ESteps.LoadAppManifest;
}
}
if (_steps == ESteps.LoadAppManifest)
{
_appManifestLoader.Update();
Progress = _appManifestLoader.Progress;
if (_appManifestLoader.IsDone == false)
return;
var manifest = _appManifestLoader.Manifest;
if (manifest == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _appManifestLoader.Error;
}
else
{
_steps = ESteps.InitVerifyingCache;
_impl.SetLocalPatchManifest(manifest);
}
} }
if (_steps == ESteps.InitVerifyingCache) if (_steps == ESteps.InitVerifyingCache)
@ -348,27 +391,10 @@ namespace YooAsset
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"The package resource {_packageName}_{_packageVersion} content has verify failed file !"; Error = $"The package resource {_packageName} content has verify failed file !";
} }
} }
} }
} }
/// <summary>
/// 加载沙盒内的补丁清单
/// 注意:在加载本地补丁清单之前,未验证过文件的哈希值
/// </summary>
private void LoadSandboxPatchManifest(string packageName, string packageVersion)
{
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
string filePath = PathHelper.MakePersistentLoadPath(fileName);
if (File.Exists(filePath))
{
YooLogger.Log("Load sandbox patch manifest file.");
string jsonData = File.ReadAllText(filePath);
var sandboxPatchManifest = PatchManifest.Deserialize(jsonData);
_impl.SetLocalPatchManifest(sandboxPatchManifest);
}
}
} }
} }

View File

@ -128,17 +128,18 @@ namespace YooAsset
} }
else else
{ {
// 解析补丁清单 // 解析补丁清单
if (ParseRemotePatchManifest(_downloader.GetText())) try
{ {
_remotePatchManifest = PatchManifest.Deserialize(_downloader.GetText());
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Succeed; Status = EOperationStatus.Succeed;
} }
else catch(System.Exception e)
{ {
_steps = ESteps.Done; _steps = ESteps.Done;
Status = EOperationStatus.Failed; Status = EOperationStatus.Failed;
Error = $"URL : {_downloader.URL} Error : remote patch manifest content is invalid"; Error = e.Message;
} }
} }
_downloader.Dispose(); _downloader.Dispose();
@ -176,23 +177,6 @@ namespace YooAsset
return _impl.GetPatchDownloadMainURL(fileName); return _impl.GetPatchDownloadMainURL(fileName);
} }
/// <summary>
/// 解析远端请求的补丁清单
/// </summary>
private bool ParseRemotePatchManifest(string content)
{
try
{
_remotePatchManifest = PatchManifest.Deserialize(content);
return true;
}
catch (Exception e)
{
YooLogger.Warning(e.ToString());
return false;
}
}
/// <summary> /// <summary>
/// 获取下载列表 /// 获取下载列表
/// </summary> /// </summary>

View File

@ -64,7 +64,7 @@ namespace YooAsset
if (string.IsNullOrEmpty(_cachedFilePath) == false) if (string.IsNullOrEmpty(_cachedFilePath) == false)
return _cachedFilePath; return _cachedFilePath;
string cacheRoot = SandboxHelper.GetCacheFolderPath(); string cacheRoot = PersistentHelper.GetCacheFolderPath();
_cachedFilePath = $"{cacheRoot}/{FileName}"; _cachedFilePath = $"{cacheRoot}/{FileName}";
return _cachedFilePath; return _cachedFilePath;
} }

View File

@ -247,6 +247,23 @@ namespace YooAsset
return false; return false;
} }
/// <summary>
/// 获取资源信息列表
/// </summary>
public AssetInfo[] GetAssetsInfoByTags(string[] tags)
{
List<AssetInfo> result = new List<AssetInfo>(100);
foreach (var patchAsset in AssetList)
{
if (patchAsset.HasTag(tags))
{
AssetInfo assetInfo = new AssetInfo(patchAsset);
result.Add(assetInfo);
}
}
return result.ToArray();
}
/// <summary> /// <summary>
/// 序列化 /// 序列化
@ -263,6 +280,8 @@ namespace YooAsset
public static PatchManifest Deserialize(string jsonData) public static PatchManifest Deserialize(string jsonData)
{ {
PatchManifest patchManifest = JsonUtility.FromJson<PatchManifest>(jsonData); PatchManifest patchManifest = JsonUtility.FromJson<PatchManifest>(jsonData);
if (patchManifest == null)
throw new System.Exception($"{nameof(PatchManifest)} deserialize object is null !");
// 检测文件版本 // 检测文件版本
if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion) if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion)

View File

@ -53,7 +53,7 @@ namespace YooAsset
} }
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags) AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
{ {
return PatchHelper.GetAssetsInfoByTags(_simulatePatchManifest, tags); return _simulatePatchManifest.GetAssetsInfoByTags(tags);
} }
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath) PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
{ {

View File

@ -64,9 +64,9 @@ namespace YooAsset
/// <summary> /// <summary>
/// 异步更新补丁清单(弱联网) /// 异步更新补丁清单(弱联网)
/// </summary> /// </summary>
public UpdateManifestOperation WeaklyUpdatePatchManifestAsync(string packageName, string packageVersion) public UpdateManifestOperation WeaklyUpdatePatchManifestAsync(string packageName)
{ {
var operation = new HostPlayModeWeaklyUpdateManifestOperation(this, packageName, packageVersion); var operation = new HostPlayModeWeaklyUpdateManifestOperation(this, packageName);
OperationSystem.StartOperation(operation); OperationSystem.StartOperation(operation);
return operation; return operation;
} }
@ -229,7 +229,7 @@ namespace YooAsset
} }
} }
return PatchHelper.ConvertToUnpackList(downloadList); return ConvertToUnpackList(downloadList);
} }
/// <summary> /// <summary>
@ -256,7 +256,7 @@ namespace YooAsset
} }
} }
return PatchHelper.ConvertToUnpackList(downloadList); return ConvertToUnpackList(downloadList);
} }
// WEB相关 // WEB相关
@ -280,7 +280,7 @@ namespace YooAsset
} }
return result; return result;
} }
public BundleInfo ConvertToDownloadInfo(PatchBundle patchBundle) private BundleInfo ConvertToDownloadInfo(PatchBundle patchBundle)
{ {
string remoteMainURL = GetPatchDownloadMainURL(patchBundle.FileName); string remoteMainURL = GetPatchDownloadMainURL(patchBundle.FileName);
string remoteFallbackURL = GetPatchDownloadFallbackURL(patchBundle.FileName); string remoteFallbackURL = GetPatchDownloadFallbackURL(patchBundle.FileName);
@ -288,6 +288,25 @@ namespace YooAsset
return bundleInfo; return bundleInfo;
} }
// 解压相关
public List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList)
{
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
foreach (var patchBundle in unpackList)
{
var bundleInfo = ConvertToUnpackInfo(patchBundle);
result.Add(bundleInfo);
}
return result;
}
public static BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
{
// 注意:我们把流加载路径指定为远端下载地址
string streamingPath = PathHelper.ConvertToWWWPath(patchBundle.StreamingFilePath);
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
return bundleInfo;
}
internal List<VerifyInfo> GetVerifyInfoList(bool weaklyUpdateMode) internal List<VerifyInfo> GetVerifyInfoList(bool weaklyUpdateMode)
{ {
List<VerifyInfo> result = new List<VerifyInfo>(LocalPatchManifest.BundleList.Count); List<VerifyInfo> result = new List<VerifyInfo>(LocalPatchManifest.BundleList.Count);
@ -379,7 +398,7 @@ namespace YooAsset
} }
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags) AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
{ {
return PatchHelper.GetAssetsInfoByTags(LocalPatchManifest, tags); return LocalPatchManifest.GetAssetsInfoByTags(tags);
} }
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath) PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
{ {

View File

@ -104,7 +104,7 @@ namespace YooAsset
} }
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags) AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
{ {
return PatchHelper.GetAssetsInfoByTags(_appPatchManifest, tags); return _appPatchManifest.GetAssetsInfoByTags(tags);
} }
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath) PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
{ {

View File

@ -40,6 +40,14 @@ namespace YooAsset
return $"{YooAssetSettings.ReportFileName}_{packageName}_{packageVersion}.json"; return $"{YooAssetSettings.ReportFileName}_{packageName}_{packageVersion}.json";
} }
/// <summary>
/// 获取补丁清单文件不带版本号的名称
/// </summary>
public static string GetPatchManifestFileNameWithoutVersion(string packageName)
{
return $"{Setting.PatchManifestFileName}_{packageName}.bytes";
}
/// <summary> /// <summary>
/// 获取补丁清单文件完整名称 /// 获取补丁清单文件完整名称
/// </summary> /// </summary>

View File

@ -76,9 +76,9 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 沙盒帮助类 /// 持久化目录帮助类
/// </summary> /// </summary>
internal static class SandboxHelper internal static class PersistentHelper
{ {
private const string CacheFolderName = "CacheFiles"; private const string CacheFolderName = "CacheFiles";
@ -109,49 +109,66 @@ namespace YooAsset
{ {
return PathHelper.MakePersistentLoadPath(CacheFolderName); return PathHelper.MakePersistentLoadPath(CacheFolderName);
} }
}
/// <summary> #region 沙盒内清单相关
/// 补丁包帮助类
/// </summary>
internal static class PatchHelper
{
/// <summary> /// <summary>
/// 获取资源信息列表 /// 获取沙盒内清单文件的路径
/// </summary> /// </summary>
public static AssetInfo[] GetAssetsInfoByTags(PatchManifest patchManifest, string[] tags) public static string GetCacheManifestFilePath(string packageName)
{ {
List<AssetInfo> result = new List<AssetInfo>(100); string fileName = YooAssetSettingsData.GetPatchManifestFileNameWithoutVersion(packageName);
foreach (var patchAsset in patchManifest.AssetList) return PathHelper.MakePersistentLoadPath(fileName);
{
if(patchAsset.HasTag(tags))
{
AssetInfo assetInfo = new AssetInfo(patchAsset);
result.Add(assetInfo);
}
}
return result.ToArray();
} }
/// <summary> /// <summary>
/// 资源解压相关 /// 加载沙盒内清单文件
/// </summary> /// </summary>
public static List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList) public static PatchManifest LoadCacheManifestFile(string packageName)
{ {
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count); YooLogger.Log($"Load sandbox patch manifest file : {packageName}");
foreach (var patchBundle in unpackList) string filePath = GetCacheManifestFilePath(packageName);
string jsonData = File.ReadAllText(filePath);
return PatchManifest.Deserialize(jsonData);
}
/// <summary>
/// 存储沙盒内清单文件
/// </summary>
public static PatchManifest SaveCacheManifestFile(string packageName, string fileContent)
{
YooLogger.Log($"Save sandbox patch manifest file : {packageName}");
var manifest = PatchManifest.Deserialize(fileContent);
string savePath = GetCacheManifestFilePath(packageName);
FileUtility.CreateFile(savePath, fileContent);
return manifest;
}
/// <summary>
/// 检测沙盒内清单文件是否存在
/// </summary>
public static bool CheckCacheManifestFileExists(string packageName)
{
string filePath = GetCacheManifestFilePath(packageName);
return File.Exists(filePath);
}
/// <summary>
/// 删除沙盒内清单文件
/// </summary>
public static bool DeleteCacheManifestFile(string packageName)
{
string filePath = GetCacheManifestFilePath(packageName);
if (File.Exists(filePath))
{ {
var bundleInfo = ConvertToUnpackInfo(patchBundle); YooLogger.Warning($"Invalid cache manifest file have been removed : {filePath}");
result.Add(bundleInfo); File.Delete(filePath);
return true;
}
else
{
return false;
} }
return result;
}
public static BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
{
// 注意:我们把流加载路径指定为远端下载地址
string streamingPath = PathHelper.ConvertToWWWPath(patchBundle.StreamingFilePath);
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
return bundleInfo;
} }
#endregion
} }
} }

View File

@ -224,7 +224,7 @@ namespace YooAsset
/// </summary> /// </summary>
public static void ClearSandbox() public static void ClearSandbox()
{ {
SandboxHelper.DeleteSandbox(); PersistentHelper.DeleteSandbox();
} }
#endregion #endregion