Init TEngine4.0.0

Init TEngine4.0.0
This commit is contained in:
ALEXTANG
2023-10-08 15:21:33 +08:00
parent 4c8c37ffd8
commit 8c3d6308b9
3773 changed files with 49313 additions and 150734 deletions

View File

@@ -0,0 +1,285 @@
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
public abstract class DownloaderOperation : AsyncOperationBase
{
private enum ESteps
{
None,
Check,
Loading,
Done,
}
private const int MAX_LOADER_COUNT = 64;
public delegate void OnDownloadOver(bool isSucceed);
public delegate void OnDownloadProgress(int totalDownloadCount, int currentDownloadCount, long totalDownloadBytes, long currentDownloadBytes);
public delegate void OnDownloadError(string fileName, string error);
public delegate void OnStartDownloadFile(string fileName, long sizeBytes);
private readonly int _downloadingMaxNumber;
private readonly int _failedTryAgain;
private readonly int _timeout;
private readonly List<BundleInfo> _downloadList;
private readonly List<DownloaderBase> _downloaders = new List<DownloaderBase>(MAX_LOADER_COUNT);
private readonly List<DownloaderBase> _removeList = new List<DownloaderBase>(MAX_LOADER_COUNT);
private readonly List<DownloaderBase> _failedList = new List<DownloaderBase>(MAX_LOADER_COUNT);
// 数据相关
private bool _isPause = false;
private long _lastDownloadBytes = 0;
private int _lastDownloadCount = 0;
private long _cachedDownloadBytes = 0;
private int _cachedDownloadCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 统计的下载文件总数量
/// </summary>
public int TotalDownloadCount { private set; get; }
/// <summary>
/// 统计的下载文件的总大小
/// </summary>
public long TotalDownloadBytes { private set; get; }
/// <summary>
/// 当前已经完成的下载总数量
/// </summary>
public int CurrentDownloadCount
{
get { return _lastDownloadCount; }
}
/// <summary>
/// 当前已经完成的下载总大小
/// </summary>
public long CurrentDownloadBytes
{
get { return _lastDownloadBytes; }
}
/// <summary>
/// 当下载器结束(无论成功或失败)
/// </summary>
public OnDownloadOver OnDownloadOverCallback { set; get; }
/// <summary>
/// 当下载进度发生变化
/// </summary>
public OnDownloadProgress OnDownloadProgressCallback { set; get; }
/// <summary>
/// 当某个文件下载失败
/// </summary>
public OnDownloadError OnDownloadErrorCallback { set; get; }
/// <summary>
/// 当开始下载某个文件
/// </summary>
public OnStartDownloadFile OnStartDownloadFileCallback { set; get; }
internal DownloaderOperation(List<BundleInfo> downloadList, int downloadingMaxNumber, int failedTryAgain, int timeout)
{
_downloadList = downloadList;
_downloadingMaxNumber = UnityEngine.Mathf.Clamp(downloadingMaxNumber, 1, MAX_LOADER_COUNT); ;
_failedTryAgain = failedTryAgain;
_timeout = timeout;
if (downloadList != null)
{
TotalDownloadCount = downloadList.Count;
foreach (var packageBundle in downloadList)
{
TotalDownloadBytes += packageBundle.Bundle.FileSize;
}
}
}
internal override void Start()
{
YooLogger.Log($"Begine to download : {TotalDownloadCount} files and {TotalDownloadBytes} bytes");
_steps = ESteps.Check;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Check)
{
if (_downloadList == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Download list is null.";
}
else
{
_steps = ESteps.Loading;
}
}
if (_steps == ESteps.Loading)
{
// 检测下载器结果
_removeList.Clear();
long downloadBytes = _cachedDownloadBytes;
foreach (var downloader in _downloaders)
{
downloadBytes += (long)downloader.DownloadedBytes;
if (downloader.IsDone() == false)
continue;
// 检测是否下载失败
if (downloader.HasError())
{
_removeList.Add(downloader);
_failedList.Add(downloader);
continue;
}
// 下载成功
_removeList.Add(downloader);
_cachedDownloadCount++;
_cachedDownloadBytes += downloader.GetDownloadFileSize();
}
// 移除已经完成的下载器(无论成功或失败)
foreach (var loader in _removeList)
{
_downloaders.Remove(loader);
}
// 如果下载进度发生变化
if (_lastDownloadBytes != downloadBytes || _lastDownloadCount != _cachedDownloadCount)
{
_lastDownloadBytes = downloadBytes;
_lastDownloadCount = _cachedDownloadCount;
Progress = (float)_lastDownloadBytes / TotalDownloadBytes;
OnDownloadProgressCallback?.Invoke(TotalDownloadCount, _lastDownloadCount, TotalDownloadBytes, _lastDownloadBytes);
}
// 动态创建新的下载器到最大数量限制
// 注意:如果期间有下载失败的文件,暂停动态创建下载器
if (_downloadList.Count > 0 && _failedList.Count == 0)
{
if (_isPause)
return;
if (_downloaders.Count < _downloadingMaxNumber)
{
int index = _downloadList.Count - 1;
var bundleInfo = _downloadList[index];
var downloader = DownloadSystem.CreateDownload(bundleInfo, _failedTryAgain, _timeout);
downloader.SendRequest();
_downloaders.Add(downloader);
_downloadList.RemoveAt(index);
OnStartDownloadFileCallback?.Invoke(bundleInfo.Bundle.BundleName, bundleInfo.Bundle.FileSize);
}
}
// 下载结算
if (_downloaders.Count == 0)
{
if (_failedList.Count > 0)
{
var failedDownloader = _failedList[0];
string fileName = failedDownloader.GetDownloadBundleName();
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to download file : {fileName}";
OnDownloadErrorCallback?.Invoke(fileName, failedDownloader.GetLastError());
OnDownloadOverCallback?.Invoke(false);
}
else
{
// 结算成功
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
OnDownloadOverCallback?.Invoke(true);
}
}
}
}
/// <summary>
/// 开始下载
/// </summary>
public void BeginDownload()
{
if (_steps == ESteps.None)
{
OperationSystem.StartOperation(this);
}
}
/// <summary>
/// 暂停下载
/// </summary>
public void PauseDownload()
{
_isPause = true;
}
/// <summary>
/// 恢复下载
/// </summary>
public void ResumeDownload()
{
_isPause = false;
}
/// <summary>
/// 取消下载
/// </summary>
public void CancelDownload()
{
if (_steps != ESteps.Done)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "User cancel.";
}
}
}
public sealed class ResourceDownloaderOperation : DownloaderOperation
{
internal ResourceDownloaderOperation(List<BundleInfo> downloadList, int downloadingMaxNumber, int failedTryAgain, int timeout)
: base(downloadList, downloadingMaxNumber, failedTryAgain, timeout)
{
}
/// <summary>
/// 创建空的下载器
/// </summary>
internal static ResourceDownloaderOperation CreateEmptyDownloader(int downloadingMaxNumber, int failedTryAgain, int timeout)
{
List<BundleInfo> downloadList = new List<BundleInfo>();
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
}
public sealed class ResourceUnpackerOperation : DownloaderOperation
{
internal ResourceUnpackerOperation(List<BundleInfo> downloadList, int downloadingMaxNumber, int failedTryAgain, int timeout)
: base(downloadList, downloadingMaxNumber, failedTryAgain, timeout)
{
}
/// <summary>
/// 创建空的解压器
/// </summary>
internal static ResourceUnpackerOperation CreateEmptyUnpacker(int upackingMaxNumber, int failedTryAgain, int timeout)
{
List<BundleInfo> downloadList = new List<BundleInfo>();
var operation = new ResourceUnpackerOperation(downloadList, upackingMaxNumber, failedTryAgain, int.MaxValue);
return operation;
}
}
}

View File

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

View File

@@ -0,0 +1,504 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 初始化操作
/// </summary>
public abstract class InitializationOperation : AsyncOperationBase
{
public string PackageVersion { protected set; get; }
}
/// <summary>
/// 编辑器下模拟模式的初始化操作
/// </summary>
internal sealed class EditorSimulateModeInitializationOperation : InitializationOperation
{
private enum ESteps
{
None,
LoadEditorManifest,
Done,
}
private readonly EditorSimulateModeImpl _impl;
private readonly string _simulateManifestFilePath;
private LoadEditorManifestOperation _loadEditorManifestOp;
private ESteps _steps = ESteps.None;
internal EditorSimulateModeInitializationOperation(EditorSimulateModeImpl impl, string simulateManifestFilePath)
{
_impl = impl;
_simulateManifestFilePath = simulateManifestFilePath;
}
internal override void Start()
{
_steps = ESteps.LoadEditorManifest;
}
internal override void Update()
{
if (_steps == ESteps.LoadEditorManifest)
{
if (_loadEditorManifestOp == null)
{
_loadEditorManifestOp = new LoadEditorManifestOperation(_simulateManifestFilePath);
OperationSystem.StartOperation(_loadEditorManifestOp);
}
if (_loadEditorManifestOp.IsDone == false)
return;
if (_loadEditorManifestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _loadEditorManifestOp.Manifest.PackageVersion;
_impl.ActiveManifest = _loadEditorManifestOp.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadEditorManifestOp.Error;
}
}
}
}
/// <summary>
/// 离线运行模式的初始化操作
/// </summary>
internal sealed class OfflinePlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
{
None,
QueryBuildinPackageVersion,
LoadBuildinManifest,
PackageCaching,
Done,
}
private readonly OfflinePlayModeImpl _impl;
private readonly string _packageName;
private QueryBuildinPackageVersionOperation _queryBuildinPackageVersionOp;
private LoadBuildinManifestOperation _loadBuildinManifestOp;
private PackageCachingOperation _cachingOperation;
private ESteps _steps = ESteps.None;
internal OfflinePlayModeInitializationOperation(OfflinePlayModeImpl impl, string packageName)
{
_impl = impl;
_packageName = packageName;
}
internal override void Start()
{
_steps = ESteps.QueryBuildinPackageVersion;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.QueryBuildinPackageVersion)
{
if (_queryBuildinPackageVersionOp == null)
{
_queryBuildinPackageVersionOp = new QueryBuildinPackageVersionOperation(_packageName);
OperationSystem.StartOperation(_queryBuildinPackageVersionOp);
}
if (_queryBuildinPackageVersionOp.IsDone == false)
return;
if (_queryBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadBuildinManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _queryBuildinPackageVersionOp.Error;
}
}
if (_steps == ESteps.LoadBuildinManifest)
{
if (_loadBuildinManifestOp == null)
{
_loadBuildinManifestOp = new LoadBuildinManifestOperation(_packageName, _queryBuildinPackageVersionOp.PackageVersion);
OperationSystem.StartOperation(_loadBuildinManifestOp);
}
Progress = _loadBuildinManifestOp.Progress;
if (_loadBuildinManifestOp.IsDone == false)
return;
if (_loadBuildinManifestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _loadBuildinManifestOp.Manifest.PackageVersion;
_impl.ActiveManifest = _loadBuildinManifestOp.Manifest;
_steps = ESteps.PackageCaching;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadBuildinManifestOp.Error;
}
}
if (_steps == ESteps.PackageCaching)
{
if (_cachingOperation == null)
{
_cachingOperation = new PackageCachingOperation(_packageName);
OperationSystem.StartOperation(_cachingOperation);
}
Progress = _cachingOperation.Progress;
if (_cachingOperation.IsDone)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
/// <summary>
/// 联机运行模式的初始化操作
/// 注意:优先从沙盒里加载清单,如果沙盒里不存在就尝试把内置清单拷贝到沙盒并加载该清单。
/// </summary>
internal sealed class HostPlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
{
None,
CheckAppFootPrint,
QueryCachePackageVersion,
TryLoadCacheManifest,
QueryBuildinPackageVersion,
UnpackBuildinManifest,
LoadBuildinManifest,
PackageCaching,
Done,
}
private readonly HostPlayModeImpl _impl;
private readonly string _packageName;
private QueryBuildinPackageVersionOperation _queryBuildinPackageVersionOp;
private QueryCachePackageVersionOperation _queryCachePackageVersionOp;
private UnpackBuildinManifestOperation _unpackBuildinManifestOp;
private LoadBuildinManifestOperation _loadBuildinManifestOp;
private LoadCacheManifestOperation _loadCacheManifestOp;
private PackageCachingOperation _cachingOperation;
private ESteps _steps = ESteps.None;
internal HostPlayModeInitializationOperation(HostPlayModeImpl impl, string packageName)
{
_impl = impl;
_packageName = packageName;
}
internal override void Start()
{
_steps = ESteps.CheckAppFootPrint;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckAppFootPrint)
{
var appFootPrint = new AppFootPrint();
appFootPrint.Load(_packageName);
// 如果水印发生变化,则说明覆盖安装后首次打开游戏
if (appFootPrint.IsDirty())
{
PersistentTools.GetPersistent(_packageName).DeleteSandboxManifestFilesFolder();
appFootPrint.Coverage(_packageName);
YooLogger.Log("Delete manifest files when application foot print dirty !");
}
_steps = ESteps.QueryCachePackageVersion;
}
if (_steps == ESteps.QueryCachePackageVersion)
{
if (_queryCachePackageVersionOp == null)
{
_queryCachePackageVersionOp = new QueryCachePackageVersionOperation(_packageName);
OperationSystem.StartOperation(_queryCachePackageVersionOp);
}
if (_queryCachePackageVersionOp.IsDone == false)
return;
if (_queryCachePackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.TryLoadCacheManifest;
}
else
{
_steps = ESteps.QueryBuildinPackageVersion;
}
}
if (_steps == ESteps.TryLoadCacheManifest)
{
if (_loadCacheManifestOp == null)
{
_loadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _queryCachePackageVersionOp.PackageVersion);
OperationSystem.StartOperation(_loadCacheManifestOp);
}
if (_loadCacheManifestOp.IsDone == false)
return;
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _loadCacheManifestOp.Manifest.PackageVersion;
_impl.ActiveManifest = _loadCacheManifestOp.Manifest;
_steps = ESteps.PackageCaching;
}
else
{
_steps = ESteps.QueryBuildinPackageVersion;
}
}
if (_steps == ESteps.QueryBuildinPackageVersion)
{
if (_queryBuildinPackageVersionOp == null)
{
_queryBuildinPackageVersionOp = new QueryBuildinPackageVersionOperation(_packageName);
OperationSystem.StartOperation(_queryBuildinPackageVersionOp);
}
if (_queryBuildinPackageVersionOp.IsDone == false)
return;
if (_queryBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.UnpackBuildinManifest;
}
else
{
// 注意为了兼容MOD模式初始化动态新增的包裹的时候如果内置清单不存在也不需要报错
_steps = ESteps.PackageCaching;
string error = _queryBuildinPackageVersionOp.Error;
YooLogger.Log($"Failed to load buildin package version file : {error}");
}
}
if (_steps == ESteps.UnpackBuildinManifest)
{
if (_unpackBuildinManifestOp == null)
{
_unpackBuildinManifestOp = new UnpackBuildinManifestOperation(_packageName, _queryBuildinPackageVersionOp.PackageVersion);
OperationSystem.StartOperation(_unpackBuildinManifestOp);
}
if (_unpackBuildinManifestOp.IsDone == false)
return;
if (_unpackBuildinManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadBuildinManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unpackBuildinManifestOp.Error;
}
}
if (_steps == ESteps.LoadBuildinManifest)
{
if (_loadBuildinManifestOp == null)
{
_loadBuildinManifestOp = new LoadBuildinManifestOperation(_packageName, _queryBuildinPackageVersionOp.PackageVersion);
OperationSystem.StartOperation(_loadBuildinManifestOp);
}
Progress = _loadBuildinManifestOp.Progress;
if (_loadBuildinManifestOp.IsDone == false)
return;
if (_loadBuildinManifestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _loadBuildinManifestOp.Manifest.PackageVersion;
_impl.ActiveManifest = _loadBuildinManifestOp.Manifest;
_steps = ESteps.PackageCaching;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadBuildinManifestOp.Error;
}
}
if (_steps == ESteps.PackageCaching)
{
if (_cachingOperation == null)
{
_cachingOperation = new PackageCachingOperation(_packageName);
OperationSystem.StartOperation(_cachingOperation);
}
Progress = _cachingOperation.Progress;
if (_cachingOperation.IsDone)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
/// <summary>
/// WebGL运行模式的初始化操作
/// </summary>
internal sealed class WebPlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
{
None,
QueryWebPackageVersion,
LoadWebManifest,
Done,
}
private readonly WebPlayModeImpl _impl;
private readonly string _packageName;
private QueryBuildinPackageVersionOperation _queryWebPackageVersionOp;
private LoadBuildinManifestOperation _loadWebManifestOp;
private ESteps _steps = ESteps.None;
internal WebPlayModeInitializationOperation(WebPlayModeImpl impl, string packageName)
{
_impl = impl;
_packageName = packageName;
}
internal override void Start()
{
_steps = ESteps.QueryWebPackageVersion;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.QueryWebPackageVersion)
{
if (_queryWebPackageVersionOp == null)
{
_queryWebPackageVersionOp = new QueryBuildinPackageVersionOperation(_packageName);
OperationSystem.StartOperation(_queryWebPackageVersionOp);
}
if (_queryWebPackageVersionOp.IsDone == false)
return;
if (_queryWebPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadWebManifest;
}
else
{
// 注意WebGL平台可能因为网络的原因会导致请求失败。如果内置清单不存在或者超时也不需要报错
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
string error = _queryWebPackageVersionOp.Error;
YooLogger.Log($"Failed to load web package version file : {error}");
}
}
if (_steps == ESteps.LoadWebManifest)
{
if (_loadWebManifestOp == null)
{
_loadWebManifestOp = new LoadBuildinManifestOperation(_packageName, _queryWebPackageVersionOp.PackageVersion);
OperationSystem.StartOperation(_loadWebManifestOp);
}
Progress = _loadWebManifestOp.Progress;
if (_loadWebManifestOp.IsDone == false)
return;
if (_loadWebManifestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _loadWebManifestOp.Manifest.PackageVersion;
_impl.ActiveManifest = _loadWebManifestOp.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadWebManifestOp.Error;
}
}
}
}
/// <summary>
/// 应用程序水印
/// </summary>
internal class AppFootPrint
{
private string _footPrint;
/// <summary>
/// 读取应用程序水印
/// </summary>
public void Load(string packageName)
{
string footPrintFilePath = PersistentTools.GetPersistent(packageName).SandboxAppFootPrintFilePath;
if (File.Exists(footPrintFilePath))
{
_footPrint = FileUtility.ReadAllText(footPrintFilePath);
}
else
{
Coverage(packageName);
}
}
/// <summary>
/// 检测水印是否发生变化
/// </summary>
public bool IsDirty()
{
#if UNITY_EDITOR
return _footPrint != Application.version;
#else
return _footPrint != Application.buildGUID;
#endif
}
/// <summary>
/// 覆盖掉水印
/// </summary>
public void Coverage(string packageName)
{
#if UNITY_EDITOR
_footPrint = Application.version;
#else
_footPrint = Application.buildGUID;
#endif
string footPrintFilePath = PersistentTools.GetPersistent(packageName).SandboxAppFootPrintFilePath;
FileUtility.WriteAllText(footPrintFilePath, _footPrint);
YooLogger.Log($"Save application foot print : {_footPrint}");
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ba3f4fc8cf6941f4a96ab928cec547e3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,240 @@
using System.IO;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
internal class DeserializeManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
DeserializeFileHeader,
PrepareAssetList,
DeserializeAssetList,
PrepareBundleList,
DeserializeBundleList,
Done,
}
private readonly BufferReader _buffer;
private int _packageAssetCount;
private int _packageBundleCount;
private int _progressTotalValue;
private ESteps _steps = ESteps.None;
/// <summary>
/// 解析的清单实例
/// </summary>
public PackageManifest Manifest { private set; get; }
public DeserializeManifestOperation(byte[] binaryData)
{
_buffer = new BufferReader(binaryData);
}
internal override void Start()
{
_steps = ESteps.DeserializeFileHeader;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
try
{
if (_steps == ESteps.DeserializeFileHeader)
{
if (_buffer.IsValid == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Buffer is invalid !";
return;
}
// 读取文件标记
uint fileSign = _buffer.ReadUInt32();
if (fileSign != YooAssetSettings.ManifestFileSign)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "The manifest file format is invalid !";
return;
}
// 读取文件版本
string fileVersion = _buffer.ReadUTF8();
if (fileVersion != YooAssetSettings.ManifestFileVersion)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"The manifest file version are not compatible : {fileVersion} != {YooAssetSettings.ManifestFileVersion}";
return;
}
// 读取文件头信息
Manifest = new PackageManifest();
Manifest.FileVersion = fileVersion;
Manifest.EnableAddressable = _buffer.ReadBool();
Manifest.LocationToLower = _buffer.ReadBool();
Manifest.IncludeAssetGUID = _buffer.ReadBool();
Manifest.OutputNameStyle = _buffer.ReadInt32();
Manifest.PackageName = _buffer.ReadUTF8();
Manifest.PackageVersion = _buffer.ReadUTF8();
// 检测配置
if (Manifest.EnableAddressable && Manifest.LocationToLower)
throw new System.Exception("Addressable not support location to lower !");
_steps = ESteps.PrepareAssetList;
}
if (_steps == ESteps.PrepareAssetList)
{
_packageAssetCount = _buffer.ReadInt32();
Manifest.AssetList = new List<PackageAsset>(_packageAssetCount);
Manifest.AssetDic = new Dictionary<string, PackageAsset>(_packageAssetCount);
if (Manifest.EnableAddressable)
Manifest.AssetPathMapping1 = new Dictionary<string, string>(_packageAssetCount * 3);
else
Manifest.AssetPathMapping1 = new Dictionary<string, string>(_packageAssetCount * 2);
if (Manifest.IncludeAssetGUID)
Manifest.AssetPathMapping2 = new Dictionary<string, string>(_packageAssetCount);
else
Manifest.AssetPathMapping2 = new Dictionary<string, string>();
_progressTotalValue = _packageAssetCount;
_steps = ESteps.DeserializeAssetList;
}
if (_steps == ESteps.DeserializeAssetList)
{
while (_packageAssetCount > 0)
{
var packageAsset = new PackageAsset();
packageAsset.Address = _buffer.ReadUTF8();
packageAsset.AssetPath = _buffer.ReadUTF8();
packageAsset.AssetGUID = _buffer.ReadUTF8();
packageAsset.AssetTags = _buffer.ReadUTF8Array();
packageAsset.BundleID = _buffer.ReadInt32();
packageAsset.DependIDs = _buffer.ReadInt32Array();
Manifest.AssetList.Add(packageAsset);
// 注意:我们不允许原始路径存在重名
string assetPath = packageAsset.AssetPath;
if (Manifest.AssetDic.ContainsKey(assetPath))
throw new System.Exception($"AssetPath have existed : {assetPath}");
else
Manifest.AssetDic.Add(assetPath, packageAsset);
// 填充AssetPathMapping1
{
string location = packageAsset.AssetPath;
if (Manifest.LocationToLower)
location = location.ToLower();
// 添加原生路径的映射
if (Manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
Manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
// 添加无后缀名路径的映射
if (Path.HasExtension(location))
{
string locationWithoutExtension = PathUtility.RemoveExtension(location);
if (Manifest.AssetPathMapping1.ContainsKey(locationWithoutExtension))
YooLogger.Warning($"Location have existed : {locationWithoutExtension}");
else
Manifest.AssetPathMapping1.Add(locationWithoutExtension, packageAsset.AssetPath);
}
}
if (Manifest.EnableAddressable)
{
string location = packageAsset.Address;
if (string.IsNullOrEmpty(location) == false)
{
if (Manifest.AssetPathMapping1.ContainsKey(location))
throw new System.Exception($"Location have existed : {location}");
else
Manifest.AssetPathMapping1.Add(location, packageAsset.AssetPath);
}
}
// 填充AssetPathMapping2
if (Manifest.IncludeAssetGUID)
{
if (Manifest.AssetPathMapping2.ContainsKey(packageAsset.AssetGUID))
throw new System.Exception($"AssetGUID have existed : {packageAsset.AssetGUID}");
else
Manifest.AssetPathMapping2.Add(packageAsset.AssetGUID, packageAsset.AssetPath);
}
_packageAssetCount--;
Progress = 1f - _packageAssetCount / _progressTotalValue;
if (OperationSystem.IsBusy)
break;
}
if (_packageAssetCount <= 0)
{
_steps = ESteps.PrepareBundleList;
}
}
if (_steps == ESteps.PrepareBundleList)
{
_packageBundleCount = _buffer.ReadInt32();
Manifest.BundleList = new List<PackageBundle>(_packageBundleCount);
Manifest.BundleDic = new Dictionary<string, PackageBundle>(_packageBundleCount);
_progressTotalValue = _packageBundleCount;
_steps = ESteps.DeserializeBundleList;
}
if (_steps == ESteps.DeserializeBundleList)
{
while (_packageBundleCount > 0)
{
var packageBundle = new PackageBundle();
packageBundle.BundleName = _buffer.ReadUTF8();
packageBundle.UnityCRC = _buffer.ReadUInt32();
packageBundle.FileHash = _buffer.ReadUTF8();
packageBundle.FileCRC = _buffer.ReadUTF8();
packageBundle.FileSize = _buffer.ReadInt64();
packageBundle.IsRawFile = _buffer.ReadBool();
packageBundle.LoadMethod = _buffer.ReadByte();
packageBundle.Tags = _buffer.ReadUTF8Array();
packageBundle.ReferenceIDs = _buffer.ReadInt32Array();
Manifest.BundleList.Add(packageBundle);
packageBundle.ParseBundle(Manifest.PackageName, Manifest.OutputNameStyle);
Manifest.BundleDic.Add(packageBundle.BundleName, packageBundle);
// 注意原始文件可能存在相同的CacheGUID
if (Manifest.CacheGUIDs.Contains(packageBundle.CacheGUID) == false)
Manifest.CacheGUIDs.Add(packageBundle.CacheGUID);
_packageBundleCount--;
Progress = 1f - _packageBundleCount / _progressTotalValue;
if (OperationSystem.IsBusy)
break;
}
if (_packageBundleCount <= 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
catch (System.Exception e)
{
Manifest = null;
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = e.Message;
}
}
}
}

View File

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

View File

@@ -0,0 +1,113 @@

namespace YooAsset
{
internal class DownloadManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
DownloadPackageHashFile,
DownloadManifestFile,
Done,
}
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebFileRequester _downloader1;
private UnityWebFileRequester _downloader2;
private ESteps _steps = ESteps.None;
private int _requestCount = 0;
internal DownloadManifestOperation(IRemoteServices remoteServices, string packageName, string packageVersion, int timeout)
{
_remoteServices = remoteServices;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void Start()
{
_requestCount = RequestHelper.GetRequestFailedCount(_packageName, nameof(DownloadManifestOperation));
_steps = ESteps.DownloadPackageHashFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadPackageHashFile)
{
if (_downloader1 == null)
{
string savePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageHashFilePath(_packageVersion);
string fileName = YooAssetSettingsData.GetPackageHashFileName(_packageName, _packageVersion);
string webURL = GetDownloadRequestURL(fileName);
YooLogger.Log($"Beginning to download package hash file : {webURL}");
_downloader1 = new UnityWebFileRequester();
_downloader1.SendRequest(webURL, savePath, _timeout);
}
_downloader1.CheckTimeout();
if (_downloader1.IsDone() == false)
return;
if (_downloader1.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader1.GetError();
RequestHelper.RecordRequestFailed(_packageName, nameof(DownloadManifestOperation));
}
else
{
_steps = ESteps.DownloadManifestFile;
}
_downloader1.Dispose();
}
if (_steps == ESteps.DownloadManifestFile)
{
if (_downloader2 == null)
{
string savePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageManifestFilePath(_packageVersion);
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_packageName, _packageVersion);
string webURL = GetDownloadRequestURL(fileName);
YooLogger.Log($"Beginning to download package manifest file : {webURL}");
_downloader2 = new UnityWebFileRequester();
_downloader2.SendRequest(webURL, savePath, _timeout);
}
_downloader2.CheckTimeout();
if (_downloader2.IsDone() == false)
return;
if (_downloader2.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader2.GetError();
RequestHelper.RecordRequestFailed(_packageName, nameof(DownloadManifestOperation));
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_downloader2.Dispose();
}
}
private string GetDownloadRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _remoteServices.GetRemoteMainURL(fileName);
else
return _remoteServices.GetRemoteFallbackURL(fileName);
}
}
}

View File

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

View File

@@ -0,0 +1,91 @@

namespace YooAsset
{
internal class LoadBuildinManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadBuildinManifest,
CheckDeserializeManifest,
Done,
}
private readonly string _buildinPackageName;
private readonly string _buildinPackageVersion;
private UnityWebDataRequester _downloader;
private DeserializeManifestOperation _deserializer;
private ESteps _steps = ESteps.None;
/// <summary>
/// 加载的清单实例
/// </summary>
public PackageManifest Manifest { private set; get; }
public LoadBuildinManifestOperation(string buildinPackageName, string buildinPackageVersion)
{
_buildinPackageName = buildinPackageName;
_buildinPackageVersion = buildinPackageVersion;
}
internal override void Start()
{
_steps = ESteps.LoadBuildinManifest;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBuildinManifest)
{
if (_downloader == null)
{
string filePath = PersistentTools.GetPersistent(_buildinPackageName).GetBuildinPackageManifestFilePath(_buildinPackageVersion);
string url = PersistentTools.ConvertToWWWPath(filePath);
_downloader = new UnityWebDataRequester();
_downloader.SendRequest(url);
}
if (_downloader.IsDone() == false)
return;
if (_downloader.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader.GetError();
}
else
{
byte[] bytesData = _downloader.GetData();
_deserializer = new DeserializeManifestOperation(bytesData);
OperationSystem.StartOperation(_deserializer);
_steps = ESteps.CheckDeserializeManifest;
}
_downloader.Dispose();
}
if (_steps == ESteps.CheckDeserializeManifest)
{
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
Manifest = _deserializer.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,141 @@
using System.IO;
namespace YooAsset
{
internal class LoadCacheManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
QueryCachePackageHash,
VerifyFileHash,
LoadCacheManifest,
CheckDeserializeManifest,
Done,
}
private readonly string _packageName;
private readonly string _packageVersion;
private QueryCachePackageHashOperation _queryCachePackageHashOp;
private DeserializeManifestOperation _deserializer;
private string _manifestFilePath;
private ESteps _steps = ESteps.None;
/// <summary>
/// 加载的清单实例
/// </summary>
public PackageManifest Manifest { private set; get; }
public LoadCacheManifestOperation(string packageName, string packageVersion)
{
_packageName = packageName;
_packageVersion = packageVersion;
}
internal override void Start()
{
_steps = ESteps.QueryCachePackageHash;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.QueryCachePackageHash)
{
if (_queryCachePackageHashOp == null)
{
_queryCachePackageHashOp = new QueryCachePackageHashOperation(_packageName, _packageVersion);
OperationSystem.StartOperation(_queryCachePackageHashOp);
}
if (_queryCachePackageHashOp.IsDone == false)
return;
if (_queryCachePackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.VerifyFileHash;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _queryCachePackageHashOp.Error;
ClearCacheFile();
}
}
if (_steps == ESteps.VerifyFileHash)
{
_manifestFilePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageManifestFilePath(_packageVersion);
if (File.Exists(_manifestFilePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Not found cache manifest file : {_manifestFilePath}";
ClearCacheFile();
return;
}
string fileHash = HashUtility.FileMD5(_manifestFilePath);
if (fileHash != _queryCachePackageHashOp.PackageHash)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify cache manifest file hash !";
ClearCacheFile();
}
else
{
_steps = ESteps.LoadCacheManifest;
}
}
if (_steps == ESteps.LoadCacheManifest)
{
byte[] bytesData = File.ReadAllBytes(_manifestFilePath);
_deserializer = new DeserializeManifestOperation(bytesData);
OperationSystem.StartOperation(_deserializer);
_steps = ESteps.CheckDeserializeManifest;
}
if (_steps == ESteps.CheckDeserializeManifest)
{
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
Manifest = _deserializer.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
ClearCacheFile();
}
}
}
private void ClearCacheFile()
{
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,主动把损坏的文件删除。
if (File.Exists(_manifestFilePath))
{
YooLogger.Warning($"Failed to load cache manifest file : {Error}");
YooLogger.Warning($"Invalid cache manifest file have been removed : {_manifestFilePath}");
File.Delete(_manifestFilePath);
}
string hashFilePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageHashFilePath(_packageVersion);
if (File.Exists(hashFilePath))
{
File.Delete(hashFilePath);
}
}
}
}

View File

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

View File

@@ -0,0 +1,76 @@
using System.IO;
namespace YooAsset
{
internal class LoadEditorManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadEditorManifest,
CheckDeserializeManifest,
Done,
}
private readonly string _manifestFilePath;
private DeserializeManifestOperation _deserializer;
private ESteps _steps = ESteps.None;
/// <summary>
/// 加载的清单实例
/// </summary>
public PackageManifest Manifest { private set; get; }
public LoadEditorManifestOperation(string manifestFilePath)
{
_manifestFilePath = manifestFilePath;
}
internal override void Start()
{
_steps = ESteps.LoadEditorManifest;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadEditorManifest)
{
if (File.Exists(_manifestFilePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Not found simulation manifest file : {_manifestFilePath}";
return;
}
YooLogger.Log($"Load editor manifest file : {_manifestFilePath}");
byte[] bytesData = FileUtility.ReadAllBytes(_manifestFilePath);
_deserializer = new DeserializeManifestOperation(bytesData);
OperationSystem.StartOperation(_deserializer);
_steps = ESteps.CheckDeserializeManifest;
}
if (_steps == ESteps.CheckDeserializeManifest)
{
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
Manifest = _deserializer.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,151 @@

namespace YooAsset
{
internal class LoadRemoteManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
DownloadPackageHashFile,
DownloadManifestFile,
VerifyFileHash,
CheckDeserializeManifest,
Done,
}
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private QueryRemotePackageHashOperation _queryRemotePackageHashOp;
private UnityWebDataRequester _downloader;
private DeserializeManifestOperation _deserializer;
private byte[] _fileData;
private ESteps _steps = ESteps.None;
private int _requestCount = 0;
/// <summary>
/// 加载的清单实例
/// </summary>
public PackageManifest Manifest { private set; get; }
internal LoadRemoteManifestOperation(IRemoteServices remoteServices, string packageName, string packageVersion, int timeout)
{
_remoteServices = remoteServices;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void Start()
{
_requestCount = RequestHelper.GetRequestFailedCount(_packageName, nameof(LoadRemoteManifestOperation));
_steps = ESteps.DownloadPackageHashFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadPackageHashFile)
{
if (_queryRemotePackageHashOp == null)
{
_queryRemotePackageHashOp = new QueryRemotePackageHashOperation(_remoteServices, _packageName, _packageVersion, _timeout);
OperationSystem.StartOperation(_queryRemotePackageHashOp);
}
if (_queryRemotePackageHashOp.IsDone == false)
return;
if (_queryRemotePackageHashOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.DownloadManifestFile;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _queryRemotePackageHashOp.Error;
}
}
if (_steps == ESteps.DownloadManifestFile)
{
if (_downloader == null)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_packageName, _packageVersion);
string webURL = GetDownloadRequestURL(fileName);
YooLogger.Log($"Beginning to download manifest file : {webURL}");
_downloader = new UnityWebDataRequester();
_downloader.SendRequest(webURL, _timeout);
}
_downloader.CheckTimeout();
if (_downloader.IsDone() == false)
return;
if (_downloader.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader.GetError();
RequestHelper.RecordRequestFailed(_packageName, nameof(LoadRemoteManifestOperation));
}
else
{
_fileData = _downloader.GetData();
_steps = ESteps.VerifyFileHash;
}
_downloader.Dispose();
}
if (_steps == ESteps.VerifyFileHash)
{
string fileHash = HashUtility.BytesMD5(_fileData);
if (fileHash != _queryRemotePackageHashOp.PackageHash)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify remote manifest file hash !";
}
else
{
_deserializer = new DeserializeManifestOperation(_fileData);
OperationSystem.StartOperation(_deserializer);
_steps = ESteps.CheckDeserializeManifest;
}
}
if (_steps == ESteps.CheckDeserializeManifest)
{
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
Manifest = _deserializer.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
private string GetDownloadRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _remoteServices.GetRemoteMainURL(fileName);
else
return _remoteServices.GetRemoteFallbackURL(fileName);
}
}
}

View File

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

View File

@@ -0,0 +1,75 @@

namespace YooAsset
{
internal class QueryBuildinPackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadBuildinPackageVersionFile,
Done,
}
private readonly string _packageName;
private UnityWebDataRequester _downloader;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
public QueryBuildinPackageVersionOperation(string packageName)
{
_packageName = packageName;
}
internal override void Start()
{
_steps = ESteps.LoadBuildinPackageVersionFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadBuildinPackageVersionFile)
{
if (_downloader == null)
{
string filePath = PersistentTools.GetPersistent(_packageName).GetBuildinPackageVersionFilePath();
string url = PersistentTools.ConvertToWWWPath(filePath);
_downloader = new UnityWebDataRequester();
_downloader.SendRequest(url);
}
if (_downloader.IsDone() == false)
return;
if (_downloader.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader.GetError();
}
else
{
PackageVersion = _downloader.GetText();
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
_downloader.Dispose();
}
}
}
}

View File

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

View File

@@ -0,0 +1,64 @@
using System.IO;
namespace YooAsset
{
internal class QueryCachePackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadCachePackageHashFile,
Done,
}
private readonly string _packageName;
private readonly string _packageVersion;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
public QueryCachePackageHashOperation(string packageName, string packageVersion)
{
_packageName = packageName;
_packageVersion = packageVersion;
}
internal override void Start()
{
_steps = ESteps.LoadCachePackageHashFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadCachePackageHashFile)
{
string filePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageHashFilePath(_packageVersion);
if (File.Exists(filePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Cache package hash file not found : {filePath}";
return;
}
PackageHash = FileUtility.ReadAllText(filePath);
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Cache package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,62 @@
using System.IO;
namespace YooAsset
{
internal class QueryCachePackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
LoadCachePackageVersionFile,
Done,
}
private readonly string _packageName;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
public QueryCachePackageVersionOperation(string packageName)
{
_packageName = packageName;
}
internal override void Start()
{
_steps = ESteps.LoadCachePackageVersionFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadCachePackageVersionFile)
{
string filePath = PersistentTools.GetPersistent(_packageName).GetSandboxPackageVersionFilePath();
if (File.Exists(filePath) == false)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Cache package version file not found : {filePath}";
return;
}
PackageVersion = FileUtility.ReadAllText(filePath);
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Cache package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,100 @@

namespace YooAsset
{
internal class QueryRemotePackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
DownloadPackageHash,
Done,
}
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebDataRequester _downloader;
private ESteps _steps = ESteps.None;
private int _requestCount = 0;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
public QueryRemotePackageHashOperation(IRemoteServices remoteServices, string packageName, string packageVersion, int timeout)
{
_remoteServices = remoteServices;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void Start()
{
_requestCount = RequestHelper.GetRequestFailedCount(_packageName, nameof(QueryRemotePackageHashOperation));
_steps = ESteps.DownloadPackageHash;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadPackageHash)
{
if (_downloader == null)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(_packageName, _packageVersion);
string webURL = GetPackageHashRequestURL(fileName);
YooLogger.Log($"Beginning to request package hash : {webURL}");
_downloader = new UnityWebDataRequester();
_downloader.SendRequest(webURL, _timeout);
}
Progress = _downloader.Progress();
_downloader.CheckTimeout();
if (_downloader.IsDone() == false)
return;
if (_downloader.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader.GetError();
RequestHelper.RecordRequestFailed(_packageName, nameof(QueryRemotePackageHashOperation));
}
else
{
PackageHash = _downloader.GetText();
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Remote package hash is empty : {_downloader.URL}";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
_downloader.Dispose();
}
}
private string GetPackageHashRequestURL(string fileName)
{
string url;
// 轮流返回请求地址
if (_requestCount % 2 == 0)
url = _remoteServices.GetRemoteMainURL(fileName);
else
url = _remoteServices.GetRemoteFallbackURL(fileName);
return url;
}
}
}

View File

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

View File

@@ -0,0 +1,104 @@

namespace YooAsset
{
internal class QueryRemotePackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
DownloadPackageVersion,
Done,
}
private readonly IRemoteServices _remoteServices;
private readonly string _packageName;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private UnityWebDataRequester _downloader;
private ESteps _steps = ESteps.None;
private int _requestCount = 0;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
public QueryRemotePackageVersionOperation(IRemoteServices remoteServices, string packageName, bool appendTimeTicks, int timeout)
{
_remoteServices = remoteServices;
_packageName = packageName;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void Start()
{
_requestCount = RequestHelper.GetRequestFailedCount(_packageName, nameof(QueryRemotePackageVersionOperation));
_steps = ESteps.DownloadPackageVersion;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadPackageVersion)
{
if (_downloader == null)
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_packageName);
string webURL = GetPackageVersionRequestURL(fileName);
YooLogger.Log($"Beginning to request package version : {webURL}");
_downloader = new UnityWebDataRequester();
_downloader.SendRequest(webURL, _timeout);
}
Progress = _downloader.Progress();
_downloader.CheckTimeout();
if (_downloader.IsDone() == false)
return;
if (_downloader.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader.GetError();
RequestHelper.RecordRequestFailed(_packageName, nameof(QueryRemotePackageVersionOperation));
}
else
{
PackageVersion = _downloader.GetText();
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Remote package version is empty : {_downloader.URL}";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
_downloader.Dispose();
}
}
private string GetPackageVersionRequestURL(string fileName)
{
string url;
// 轮流返回请求地址
if (_requestCount % 2 == 0)
url = _remoteServices.GetRemoteMainURL(fileName);
else
url = _remoteServices.GetRemoteFallbackURL(fileName);
// 在URL末尾添加时间戳
if (_appendTimeTicks)
return $"{url}?{System.DateTime.UtcNow.Ticks}";
else
return url;
}
}
}

View File

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

View File

@@ -0,0 +1,94 @@

namespace YooAsset
{
internal class UnpackBuildinManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
UnpackManifestHashFile,
UnpackManifestFile,
Done,
}
private readonly string _buildinPackageName;
private readonly string _buildinPackageVersion;
private UnityWebFileRequester _downloader1;
private UnityWebFileRequester _downloader2;
private ESteps _steps = ESteps.None;
public UnpackBuildinManifestOperation(string buildinPackageName, string buildinPackageVersion)
{
_buildinPackageName = buildinPackageName;
_buildinPackageVersion = buildinPackageVersion;
}
internal override void Start()
{
_steps = ESteps.UnpackManifestHashFile;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.UnpackManifestHashFile)
{
if (_downloader1 == null)
{
var persistent = PersistentTools.GetPersistent(_buildinPackageName);
string savePath = persistent.GetSandboxPackageHashFilePath(_buildinPackageVersion);
string filePath = persistent.GetBuildinPackageHashFilePath(_buildinPackageVersion);
string url = PersistentTools.ConvertToWWWPath(filePath);
_downloader1 = new UnityWebFileRequester();
_downloader1.SendRequest(url, savePath);
}
if (_downloader1.IsDone() == false)
return;
if (_downloader1.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader1.GetError();
}
else
{
_steps = ESteps.UnpackManifestFile;
}
_downloader1.Dispose();
}
if (_steps == ESteps.UnpackManifestFile)
{
if (_downloader2 == null)
{
var persistent = PersistentTools.GetPersistent(_buildinPackageName);
string savePath = persistent.GetSandboxPackageManifestFilePath(_buildinPackageVersion);
string filePath = persistent.GetBuildinPackageManifestFilePath(_buildinPackageVersion);
string url = PersistentTools.ConvertToWWWPath(filePath);
_downloader2 = new UnityWebFileRequester();
_downloader2.SendRequest(url, savePath);
}
if (_downloader2.IsDone() == false)
return;
if (_downloader2.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloader2.GetError();
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_downloader2.Dispose();
}
}
}
}

View File

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

View File

@@ -0,0 +1,299 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
public abstract class PreDownloadContentOperation : AsyncOperationBase
{
/// <summary>
/// 创建资源下载器,用于下载当前资源版本所有的资源包文件
/// </summary>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
/// <param name="timeout">超时时间</param>
public virtual ResourceDownloaderOperation CreateResourceDownloader(int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
/// <summary>
/// 创建资源下载器,用于下载指定的资源标签关联的资源包文件
/// </summary>
/// <param name="tag">资源标签</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
/// <param name="timeout">超时时间</param>
public virtual ResourceDownloaderOperation CreateResourceDownloader(string tag, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
/// <summary>
/// 创建资源下载器,用于下载指定的资源标签列表关联的资源包文件
/// </summary>
/// <param name="tags">资源标签列表</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
/// <param name="timeout">超时时间</param>
public virtual ResourceDownloaderOperation CreateResourceDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
/// <summary>
/// 创建资源下载器,用于下载指定的资源依赖的资源包文件
/// </summary>
/// <param name="location">资源定位地址</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
/// <param name="timeout">超时时间</param>
public virtual ResourceDownloaderOperation CreateBundleDownloader(string location, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
/// <summary>
/// 创建资源下载器,用于下载指定的资源列表依赖的资源包文件
/// </summary>
/// <param name="locations">资源定位地址列表</param>
/// <param name="downloadingMaxNumber">同时下载的最大文件数</param>
/// <param name="failedTryAgain">下载失败的重试次数</param>
/// <param name="timeout">超时时间</param>
public virtual ResourceDownloaderOperation CreateBundleDownloader(string[] locations, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
}
internal class EditorPlayModePreDownloadContentOperation : PreDownloadContentOperation
{
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
internal class OfflinePlayModePreDownloadContentOperation : PreDownloadContentOperation
{
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
internal class HostPlayModePreDownloadContentOperation : PreDownloadContentOperation
{
private enum ESteps
{
None,
CheckActiveManifest,
TryLoadCacheManifest,
DownloadManifest,
LoadCacheManifest,
CheckDeserializeManifest,
Done,
}
private readonly HostPlayModeImpl _impl;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private LoadCacheManifestOperation _tryLoadCacheManifestOp;
private LoadCacheManifestOperation _loadCacheManifestOp;
private DownloadManifestOperation _downloadManifestOp;
private PackageManifest _manifest;
private ESteps _steps = ESteps.None;
internal HostPlayModePreDownloadContentOperation(HostPlayModeImpl impl, string packageName, string packageVersion, int timeout)
{
_impl = impl;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void Start()
{
_steps = ESteps.CheckActiveManifest;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckActiveManifest)
{
// 检测当前激活的清单对象
if (_impl.ActiveManifest != null)
{
if (_impl.ActiveManifest.PackageVersion == _packageVersion)
{
_manifest = _impl.ActiveManifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
}
_steps = ESteps.TryLoadCacheManifest;
}
if (_steps == ESteps.TryLoadCacheManifest)
{
if (_tryLoadCacheManifestOp == null)
{
_tryLoadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _packageVersion);
OperationSystem.StartOperation(_tryLoadCacheManifestOp);
}
if (_tryLoadCacheManifestOp.IsDone == false)
return;
if (_tryLoadCacheManifestOp.Status == EOperationStatus.Succeed)
{
_manifest = _tryLoadCacheManifestOp.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.DownloadManifest;
}
}
if (_steps == ESteps.DownloadManifest)
{
if (_downloadManifestOp == null)
{
_downloadManifestOp = new DownloadManifestOperation(_impl.RemoteServices, _packageName, _packageVersion, _timeout);
OperationSystem.StartOperation(_downloadManifestOp);
}
if (_downloadManifestOp.IsDone == false)
return;
if (_downloadManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadCacheManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadManifestOp.Error;
}
}
if (_steps == ESteps.LoadCacheManifest)
{
if (_loadCacheManifestOp == null)
{
_loadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _packageVersion);
OperationSystem.StartOperation(_loadCacheManifestOp);
}
if (_loadCacheManifestOp.IsDone == false)
return;
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
{
_manifest = _loadCacheManifestOp.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCacheManifestOp.Error;
}
}
}
public override ResourceDownloaderOperation CreateResourceDownloader(int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
if (Status != EOperationStatus.Succeed)
{
YooLogger.Warning($"{nameof(PreDownloadContentOperation)} status is not succeed !");
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
List<BundleInfo> downloadList = _impl.GetDownloadListByAll(_manifest);
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
public override ResourceDownloaderOperation CreateResourceDownloader(string tag, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
if (Status != EOperationStatus.Succeed)
{
YooLogger.Warning($"{nameof(PreDownloadContentOperation)} status is not succeed !");
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
List<BundleInfo> downloadList = _impl.GetDownloadListByTags(_manifest, new string[] { tag });
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
public override ResourceDownloaderOperation CreateResourceDownloader(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
if (Status != EOperationStatus.Succeed)
{
YooLogger.Warning($"{nameof(PreDownloadContentOperation)} status is not succeed !");
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
List<BundleInfo> downloadList = _impl.GetDownloadListByTags(_manifest, tags);
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
public override ResourceDownloaderOperation CreateBundleDownloader(string location, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
if (Status != EOperationStatus.Succeed)
{
YooLogger.Warning($"{nameof(PreDownloadContentOperation)} status is not succeed !");
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
List<AssetInfo> assetInfos = new List<AssetInfo>();
var assetInfo = _manifest.ConvertLocationToAssetInfo(location, null);
assetInfos.Add(assetInfo);
List<BundleInfo> downloadList = _impl.GetDownloadListByPaths(_manifest, assetInfos.ToArray());
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
public override ResourceDownloaderOperation CreateBundleDownloader(string[] locations, int downloadingMaxNumber, int failedTryAgain, int timeout = 60)
{
if (Status != EOperationStatus.Succeed)
{
YooLogger.Warning($"{nameof(PreDownloadContentOperation)} status is not succeed !");
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
}
List<AssetInfo> assetInfos = new List<AssetInfo>(locations.Length);
foreach (var location in locations)
{
var assetInfo = _manifest.ConvertLocationToAssetInfo(location, null);
assetInfos.Add(assetInfo);
}
List<BundleInfo> downloadList = _impl.GetDownloadListByPaths(_manifest, assetInfos.ToArray());
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
return operation;
}
}
internal class WebPlayModePreDownloadContentOperation : PreDownloadContentOperation
{
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
}

View File

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

View File

@@ -0,0 +1,314 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset
{
/// <summary>
/// 向远端请求并更新清单
/// </summary>
public abstract class UpdatePackageManifestOperation : AsyncOperationBase
{
/// <summary>
/// 保存当前清单的版本,用于下次启动时自动加载的版本。
/// </summary>
public virtual void SavePackageVersion() { }
}
/// <summary>
/// 编辑器下模拟运行的更新清单操作
/// </summary>
internal sealed class EditorPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
{
public EditorPlayModeUpdatePackageManifestOperation()
{
}
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
/// <summary>
/// 离线模式的更新清单操作
/// </summary>
internal sealed class OfflinePlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
{
public OfflinePlayModeUpdatePackageManifestOperation()
{
}
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
/// <summary>
/// 联机模式的更新清单操作
/// 注意:优先加载沙盒里缓存的清单文件,如果缓存没找到就下载远端清单文件,并保存到本地。
/// </summary>
internal sealed class HostPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
{
private enum ESteps
{
None,
CheckParams,
CheckActiveManifest,
TryLoadCacheManifest,
DownloadManifest,
LoadCacheManifest,
CheckDeserializeManifest,
Done,
}
private readonly HostPlayModeImpl _impl;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly bool _autoSaveVersion;
private readonly int _timeout;
private LoadCacheManifestOperation _tryLoadCacheManifestOp;
private LoadCacheManifestOperation _loadCacheManifestOp;
private DownloadManifestOperation _downloadManifestOp;
private ESteps _steps = ESteps.None;
internal HostPlayModeUpdatePackageManifestOperation(HostPlayModeImpl impl, string packageName, string packageVersion, bool autoSaveVersion, int timeout)
{
_impl = impl;
_packageName = packageName;
_packageVersion = packageVersion;
_autoSaveVersion = autoSaveVersion;
_timeout = timeout;
}
internal override void Start()
{
_steps = ESteps.CheckParams;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckParams)
{
if (string.IsNullOrEmpty(_packageName))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Package name is null or empty.";
return;
}
if (string.IsNullOrEmpty(_packageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Package version is null or empty.";
return;
}
_steps = ESteps.CheckActiveManifest;
}
if (_steps == ESteps.CheckActiveManifest)
{
// 检测当前激活的清单对象
if (_impl.ActiveManifest != null && _impl.ActiveManifest.PackageVersion == _packageVersion)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.TryLoadCacheManifest;
}
}
if (_steps == ESteps.TryLoadCacheManifest)
{
if (_tryLoadCacheManifestOp == null)
{
_tryLoadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _packageVersion);
OperationSystem.StartOperation(_tryLoadCacheManifestOp);
}
if (_tryLoadCacheManifestOp.IsDone == false)
return;
if (_tryLoadCacheManifestOp.Status == EOperationStatus.Succeed)
{
_impl.ActiveManifest = _tryLoadCacheManifestOp.Manifest;
if (_autoSaveVersion)
SavePackageVersion();
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.DownloadManifest;
}
}
if (_steps == ESteps.DownloadManifest)
{
if (_downloadManifestOp == null)
{
_downloadManifestOp = new DownloadManifestOperation(_impl.RemoteServices, _packageName, _packageVersion, _timeout);
OperationSystem.StartOperation(_downloadManifestOp);
}
if (_downloadManifestOp.IsDone == false)
return;
if (_downloadManifestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.LoadCacheManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _downloadManifestOp.Error;
}
}
if (_steps == ESteps.LoadCacheManifest)
{
if (_loadCacheManifestOp == null)
{
_loadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _packageVersion);
OperationSystem.StartOperation(_loadCacheManifestOp);
}
if (_loadCacheManifestOp.IsDone == false)
return;
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
{
_impl.ActiveManifest = _loadCacheManifestOp.Manifest;
if (_autoSaveVersion)
SavePackageVersion();
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCacheManifestOp.Error;
}
}
}
public override void SavePackageVersion()
{
_impl.FlushManifestVersionFile();
}
}
/// <summary>
/// WebGL模式的更新清单操作
/// </summary>
internal sealed class WebPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
{
private enum ESteps
{
None,
CheckParams,
CheckActiveManifest,
LoadRemoteManifest,
Done,
}
private readonly WebPlayModeImpl _impl;
private readonly string _packageName;
private readonly string _packageVersion;
private readonly int _timeout;
private LoadRemoteManifestOperation _loadCacheManifestOp;
private ESteps _steps = ESteps.None;
internal WebPlayModeUpdatePackageManifestOperation(WebPlayModeImpl impl, string packageName, string packageVersion, int timeout)
{
_impl = impl;
_packageName = packageName;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void Start()
{
_steps = ESteps.CheckParams;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckParams)
{
if (string.IsNullOrEmpty(_packageName))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Package name is null or empty.";
return;
}
if (string.IsNullOrEmpty(_packageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Package version is null or empty.";
return;
}
_steps = ESteps.CheckActiveManifest;
}
if (_steps == ESteps.CheckActiveManifest)
{
// 检测当前激活的清单对象
if (_impl.ActiveManifest != null && _impl.ActiveManifest.PackageVersion == _packageVersion)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.LoadRemoteManifest;
}
}
if (_steps == ESteps.LoadRemoteManifest)
{
if (_loadCacheManifestOp == null)
{
_loadCacheManifestOp = new LoadRemoteManifestOperation(_impl.RemoteServices, _packageName, _packageVersion, _timeout);
OperationSystem.StartOperation(_loadCacheManifestOp);
}
if (_loadCacheManifestOp.IsDone == false)
return;
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
{
_impl.ActiveManifest = _loadCacheManifestOp.Manifest;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadCacheManifestOp.Error;
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,169 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset
{
/// <summary>
/// 请求远端包裹的最新版本
/// </summary>
public abstract class UpdatePackageVersionOperation : AsyncOperationBase
{
/// <summary>
/// 当前最新的包裹版本
/// </summary>
public string PackageVersion { protected set; get; }
}
/// <summary>
/// 编辑器下模拟模式的请求远端包裹的最新版本
/// </summary>
internal sealed class EditorPlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
{
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
/// <summary>
/// 离线模式的请求远端包裹的最新版本
/// </summary>
internal sealed class OfflinePlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
{
internal override void Start()
{
Status = EOperationStatus.Succeed;
}
internal override void Update()
{
}
}
/// <summary>
/// 联机模式的请求远端包裹的最新版本
/// </summary>
internal sealed class HostPlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
{
private enum ESteps
{
None,
QueryRemotePackageVersion,
Done,
}
private readonly HostPlayModeImpl _impl;
private readonly string _packageName;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private QueryRemotePackageVersionOperation _queryRemotePackageVersionOp;
private ESteps _steps = ESteps.None;
internal HostPlayModeUpdatePackageVersionOperation(HostPlayModeImpl impl, string packageName, bool appendTimeTicks, int timeout)
{
_impl = impl;
_packageName = packageName;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void Start()
{
_steps = ESteps.QueryRemotePackageVersion;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.QueryRemotePackageVersion)
{
if (_queryRemotePackageVersionOp == null)
{
_queryRemotePackageVersionOp = new QueryRemotePackageVersionOperation(_impl.RemoteServices, _packageName, _appendTimeTicks, _timeout);
OperationSystem.StartOperation(_queryRemotePackageVersionOp);
}
if (_queryRemotePackageVersionOp.IsDone == false)
return;
if (_queryRemotePackageVersionOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _queryRemotePackageVersionOp.PackageVersion;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _queryRemotePackageVersionOp.Error;
}
}
}
}
/// <summary>
/// WebGL模式的请求远端包裹的最新版本
/// </summary>
internal sealed class WebPlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
{
private enum ESteps
{
None,
QueryRemotePackageVersion,
Done,
}
private readonly WebPlayModeImpl _impl;
private readonly string _packageName;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private QueryRemotePackageVersionOperation _queryRemotePackageVersionOp;
private ESteps _steps = ESteps.None;
internal WebPlayModeUpdatePackageVersionOperation(WebPlayModeImpl impl, string packageName, bool appendTimeTicks, int timeout)
{
_impl = impl;
_packageName = packageName;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void Start()
{
_steps = ESteps.QueryRemotePackageVersion;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.QueryRemotePackageVersion)
{
if (_queryRemotePackageVersionOp == null)
{
_queryRemotePackageVersionOp = new QueryRemotePackageVersionOperation(_impl.RemoteServices, _packageName, _appendTimeTicks, _timeout);
OperationSystem.StartOperation(_queryRemotePackageVersionOp);
}
if (_queryRemotePackageVersionOp.IsDone == false)
return;
if (_queryRemotePackageVersionOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _queryRemotePackageVersionOp.PackageVersion;
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _queryRemotePackageVersionOp.Error;
}
}
}
}
}

View File

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