mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Init TEngine4.0.0
Init TEngine4.0.0
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public class AssetInfo
|
||||
{
|
||||
private readonly PackageAsset _packageAsset;
|
||||
private string _providerGUID;
|
||||
|
||||
/// <summary>
|
||||
/// 资源类型
|
||||
/// </summary>
|
||||
public System.Type AssetType { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string Error { private set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 唯一标识符
|
||||
/// </summary>
|
||||
internal string GUID
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_providerGUID) == false)
|
||||
return _providerGUID;
|
||||
|
||||
if (AssetType == null)
|
||||
_providerGUID = $"{AssetPath}[null]";
|
||||
else
|
||||
_providerGUID = $"{AssetPath}[{AssetType.Name}]";
|
||||
return _providerGUID;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 身份是否无效
|
||||
/// </summary>
|
||||
internal bool IsInvalid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _packageAsset == null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 可寻址地址
|
||||
/// </summary>
|
||||
public string Address
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_packageAsset == null)
|
||||
return string.Empty;
|
||||
return _packageAsset.Address;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径
|
||||
/// </summary>
|
||||
public string AssetPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_packageAsset == null)
|
||||
return string.Empty;
|
||||
return _packageAsset.AssetPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private AssetInfo()
|
||||
{
|
||||
// 注意:禁止从外部创建该类
|
||||
}
|
||||
internal AssetInfo(PackageAsset packageAsset, System.Type assetType)
|
||||
{
|
||||
if (packageAsset == null)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
_providerGUID = string.Empty;
|
||||
_packageAsset = packageAsset;
|
||||
AssetType = assetType;
|
||||
Error = string.Empty;
|
||||
}
|
||||
internal AssetInfo(PackageAsset packageAsset)
|
||||
{
|
||||
if (packageAsset == null)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
_providerGUID = string.Empty;
|
||||
_packageAsset = packageAsset;
|
||||
AssetType = null;
|
||||
Error = string.Empty;
|
||||
}
|
||||
internal AssetInfo(string error)
|
||||
{
|
||||
_providerGUID = string.Empty;
|
||||
_packageAsset = null;
|
||||
AssetType = null;
|
||||
Error = error;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07db4f624e6cf80468fadd9e94691017
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,84 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BundleInfo
|
||||
{
|
||||
public enum ELoadMode
|
||||
{
|
||||
None,
|
||||
LoadFromDelivery,
|
||||
LoadFromStreaming,
|
||||
LoadFromCache,
|
||||
LoadFromRemote,
|
||||
LoadFromEditor,
|
||||
}
|
||||
|
||||
public readonly PackageBundle Bundle;
|
||||
public readonly ELoadMode LoadMode;
|
||||
|
||||
/// <summary>
|
||||
/// 远端下载地址
|
||||
/// </summary>
|
||||
public string RemoteMainURL { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 远端下载备用地址
|
||||
/// </summary>
|
||||
public string RemoteFallbackURL { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开发者分发的文件地址
|
||||
/// </summary>
|
||||
public string DeliveryFilePath { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 开发者分发的文件偏移量
|
||||
/// </summary>
|
||||
public ulong DeliveryFileOffset { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 注意:该字段只用于帮助编辑器下的模拟模式。
|
||||
/// </summary>
|
||||
public string[] IncludeAssets;
|
||||
|
||||
|
||||
private BundleInfo()
|
||||
{
|
||||
}
|
||||
public BundleInfo(PackageBundle bundle, ELoadMode loadMode, string mainURL, string fallbackURL)
|
||||
{
|
||||
Bundle = bundle;
|
||||
LoadMode = loadMode;
|
||||
RemoteMainURL = mainURL;
|
||||
RemoteFallbackURL = fallbackURL;
|
||||
DeliveryFilePath = string.Empty;
|
||||
DeliveryFileOffset = 0;
|
||||
}
|
||||
public BundleInfo(PackageBundle bundle, ELoadMode loadMode, string deliveryFilePath, ulong deliveryFileOffset)
|
||||
{
|
||||
Bundle = bundle;
|
||||
LoadMode = loadMode;
|
||||
RemoteMainURL = string.Empty;
|
||||
RemoteFallbackURL = string.Empty;
|
||||
DeliveryFilePath = deliveryFilePath;
|
||||
DeliveryFileOffset = deliveryFileOffset;
|
||||
}
|
||||
public BundleInfo(PackageBundle bundle, ELoadMode loadMode)
|
||||
{
|
||||
Bundle = bundle;
|
||||
LoadMode = loadMode;
|
||||
RemoteMainURL = string.Empty;
|
||||
RemoteFallbackURL = string.Empty;
|
||||
DeliveryFilePath = string.Empty;
|
||||
DeliveryFileOffset = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为JAR包内文件
|
||||
/// </summary>
|
||||
public static bool IsBuildinJarFile(string streamingPath)
|
||||
{
|
||||
return streamingPath.StartsWith("jar:");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2939a2b9862f05545969cc5fcb378bd8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class ManifestTools
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// 序列化(JSON文件)
|
||||
/// </summary>
|
||||
public static void SerializeToJson(string savePath, PackageManifest manifest)
|
||||
{
|
||||
string json = JsonUtility.ToJson(manifest, true);
|
||||
FileUtility.WriteAllText(savePath, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化(二进制文件)
|
||||
/// </summary>
|
||||
public static void SerializeToBinary(string savePath, PackageManifest manifest)
|
||||
{
|
||||
using (FileStream fs = new FileStream(savePath, FileMode.Create))
|
||||
{
|
||||
// 创建缓存器
|
||||
BufferWriter buffer = new BufferWriter(YooAssetSettings.ManifestFileMaxSize);
|
||||
|
||||
// 写入文件标记
|
||||
buffer.WriteUInt32(YooAssetSettings.ManifestFileSign);
|
||||
|
||||
// 写入文件版本
|
||||
buffer.WriteUTF8(manifest.FileVersion);
|
||||
|
||||
// 写入文件头信息
|
||||
buffer.WriteBool(manifest.EnableAddressable);
|
||||
buffer.WriteBool(manifest.LocationToLower);
|
||||
buffer.WriteBool(manifest.IncludeAssetGUID);
|
||||
buffer.WriteInt32(manifest.OutputNameStyle);
|
||||
buffer.WriteUTF8(manifest.PackageName);
|
||||
buffer.WriteUTF8(manifest.PackageVersion);
|
||||
|
||||
// 写入资源列表
|
||||
buffer.WriteInt32(manifest.AssetList.Count);
|
||||
for (int i = 0; i < manifest.AssetList.Count; i++)
|
||||
{
|
||||
var packageAsset = manifest.AssetList[i];
|
||||
buffer.WriteUTF8(packageAsset.Address);
|
||||
buffer.WriteUTF8(packageAsset.AssetPath);
|
||||
buffer.WriteUTF8(packageAsset.AssetGUID);
|
||||
buffer.WriteUTF8Array(packageAsset.AssetTags);
|
||||
buffer.WriteInt32(packageAsset.BundleID);
|
||||
buffer.WriteInt32Array(packageAsset.DependIDs);
|
||||
}
|
||||
|
||||
// 写入资源包列表
|
||||
buffer.WriteInt32(manifest.BundleList.Count);
|
||||
for (int i = 0; i < manifest.BundleList.Count; i++)
|
||||
{
|
||||
var packageBundle = manifest.BundleList[i];
|
||||
buffer.WriteUTF8(packageBundle.BundleName);
|
||||
buffer.WriteUInt32(packageBundle.UnityCRC);
|
||||
buffer.WriteUTF8(packageBundle.FileHash);
|
||||
buffer.WriteUTF8(packageBundle.FileCRC);
|
||||
buffer.WriteInt64(packageBundle.FileSize);
|
||||
buffer.WriteBool(packageBundle.IsRawFile);
|
||||
buffer.WriteByte(packageBundle.LoadMethod);
|
||||
buffer.WriteUTF8Array(packageBundle.Tags);
|
||||
buffer.WriteInt32Array(packageBundle.ReferenceIDs);
|
||||
}
|
||||
|
||||
// 写入文件流
|
||||
buffer.WriteToStream(fs);
|
||||
fs.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化(JSON文件)
|
||||
/// </summary>
|
||||
public static PackageManifest DeserializeFromJson(string jsonContent)
|
||||
{
|
||||
return JsonUtility.FromJson<PackageManifest>(jsonContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化(二进制文件)
|
||||
/// </summary>
|
||||
public static PackageManifest DeserializeFromBinary(byte[] binaryData)
|
||||
{
|
||||
// 创建缓存器
|
||||
BufferReader buffer = new BufferReader(binaryData);
|
||||
|
||||
// 读取文件标记
|
||||
uint fileSign = buffer.ReadUInt32();
|
||||
if (fileSign != YooAssetSettings.ManifestFileSign)
|
||||
throw new Exception("Invalid manifest file !");
|
||||
|
||||
// 读取文件版本
|
||||
string fileVersion = buffer.ReadUTF8();
|
||||
if (fileVersion != YooAssetSettings.ManifestFileVersion)
|
||||
throw new Exception($"The manifest file version are not compatible : {fileVersion} != {YooAssetSettings.ManifestFileVersion}");
|
||||
|
||||
PackageManifest 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 Exception("Addressable not support location to lower !");
|
||||
|
||||
// 读取资源列表
|
||||
int packageAssetCount = buffer.ReadInt32();
|
||||
manifest.AssetList = new List<PackageAsset>(packageAssetCount);
|
||||
for (int i = 0; i < packageAssetCount; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// 读取资源包列表
|
||||
int packageBundleCount = buffer.ReadInt32();
|
||||
manifest.BundleList = new List<PackageBundle>(packageBundleCount);
|
||||
for (int i = 0; i < packageBundleCount; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 填充BundleDic
|
||||
manifest.BundleDic = new Dictionary<string, PackageBundle>(manifest.BundleList.Count);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
packageBundle.ParseBundle(manifest.PackageName, manifest.OutputNameStyle);
|
||||
manifest.BundleDic.Add(packageBundle.BundleName, packageBundle);
|
||||
}
|
||||
|
||||
// 填充AssetDic
|
||||
manifest.AssetDic = new Dictionary<string, PackageAsset>(manifest.AssetList.Count);
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
// 注意:我们不允许原始路径存在重名
|
||||
string assetPath = packageAsset.AssetPath;
|
||||
if (manifest.AssetDic.ContainsKey(assetPath))
|
||||
throw new Exception($"AssetPath have existed : {assetPath}");
|
||||
else
|
||||
manifest.AssetDic.Add(assetPath, packageAsset);
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static string GetRemoteBundleFileExtension(string bundleName)
|
||||
{
|
||||
string fileExtension = Path.GetExtension(bundleName);
|
||||
return fileExtension;
|
||||
}
|
||||
public static string GetRemoteBundleFileName(int nameStyle, string bundleName, string fileExtension, string fileHash)
|
||||
{
|
||||
if (nameStyle == 1) //HashName
|
||||
{
|
||||
return StringUtility.Format("{0}{1}", fileHash, fileExtension);
|
||||
}
|
||||
else if (nameStyle == 4) //BundleName_HashName
|
||||
{
|
||||
string fileName = bundleName.Remove(bundleName.LastIndexOf('.'));
|
||||
return StringUtility.Format("{0}_{1}{2}", fileName, fileHash, fileExtension);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException($"Invalid name style : {nameStyle}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为解压BundleInfo
|
||||
/// </summary>
|
||||
public static BundleInfo ConvertToUnpackInfo(PackageBundle packageBundle)
|
||||
{
|
||||
// 注意:我们把流加载路径指定为远端下载地址
|
||||
string streamingPath = PersistentTools.ConvertToWWWPath(packageBundle.StreamingFilePath);
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量转换为解压BundleInfo
|
||||
/// </summary>
|
||||
public static List<BundleInfo> ConvertToUnpackInfos(List<PackageBundle> unpackList)
|
||||
{
|
||||
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
|
||||
foreach (var packageBundle in unpackList)
|
||||
{
|
||||
var bundleInfo = ConvertToUnpackInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1014f7c3c05ebab4d8023b27f97a2119
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4812fd895ef2d7e4a97956be2c6f8170
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96fc897d22c24d64b9faa531c0573c44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a44ad228b117d0047ab80e7a442459b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba3f4fc8cf6941f4a96ab928cec547e3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a800be1f31ec6364f8cdd0d8c7eef269
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fccaa9437207a174d858ce44f14f5a03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3a2fe7d8d4747d43b3ac48097341e36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5067db2d5b2aa1240aef2f9a952a2e0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 246df4d20b431c648a0821231a805e6b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 486ce3e7ad16f2948a36d49ecabd76b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdc251ea99d82e54199dfba540f2814d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60db6a6586340664ab7e9f85cec0eef4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29a2cbdd051ba1247a24693d56cdc2c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef77260f58172dd42ad10cfb862b78ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d702a1a39789a34da99cbb854708b82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a7685e67b0e948439ffba34513b78c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51f7a5e97aff1a646972c4ea11612947
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 250c5da7ab03e724f8c328de5238e433
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60bb21def73049e4f83a108d0e741301
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 可寻址地址
|
||||
/// </summary>
|
||||
public string Address;
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径
|
||||
/// </summary>
|
||||
public string AssetPath;
|
||||
|
||||
/// <summary>
|
||||
/// 资源GUID
|
||||
/// </summary>
|
||||
public string AssetGUID;
|
||||
|
||||
/// <summary>
|
||||
/// 资源的分类标签
|
||||
/// </summary>
|
||||
public string[] AssetTags;
|
||||
|
||||
/// <summary>
|
||||
/// 所属资源包ID
|
||||
/// </summary>
|
||||
public int BundleID;
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的资源包ID列表
|
||||
/// </summary>
|
||||
public int[] DependIDs;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含Tag
|
||||
/// </summary>
|
||||
public bool HasTag(string[] tags)
|
||||
{
|
||||
if (tags == null || tags.Length == 0)
|
||||
return false;
|
||||
if (AssetTags == null || AssetTags.Length == 0)
|
||||
return false;
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (AssetTags.Contains(tag))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df359cc7c21634d41b5d05f09ca59cf2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageBundle
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
|
||||
/// <summary>
|
||||
/// Unity引擎生成的CRC
|
||||
/// </summary>
|
||||
public uint UnityCRC;
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值
|
||||
/// </summary>
|
||||
public string FileHash;
|
||||
|
||||
/// <summary>
|
||||
/// 文件校验码
|
||||
/// </summary>
|
||||
public string FileCRC;
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小(字节数)
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile;
|
||||
|
||||
/// <summary>
|
||||
/// 加载方法
|
||||
/// </summary>
|
||||
public byte LoadMethod;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包的分类标签
|
||||
/// </summary>
|
||||
public string[] Tags;
|
||||
|
||||
/// <summary>
|
||||
/// 引用该资源包的ID列表
|
||||
/// </summary>
|
||||
public int[] ReferenceIDs;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 所属的包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存GUID
|
||||
/// </summary>
|
||||
public string CacheGUID
|
||||
{
|
||||
get { return FileHash; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存的数据文件路径
|
||||
/// </summary>
|
||||
private string _cachedDataFilePath;
|
||||
public string CachedDataFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cachedDataFilePath) == false)
|
||||
return _cachedDataFilePath;
|
||||
|
||||
string folderName = FileHash.Substring(0, 2);
|
||||
if (IsRawFile)
|
||||
{
|
||||
string cacheRoot = PersistentTools.GetPersistent(PackageName).SandboxCacheRawFilesRoot;
|
||||
_cachedDataFilePath = PathUtility.Combine(cacheRoot, folderName, CacheGUID, YooAssetSettings.CacheBundleDataFileName);
|
||||
_cachedDataFilePath += _fileExtension;
|
||||
}
|
||||
else
|
||||
{
|
||||
string cacheRoot = PersistentTools.GetPersistent(PackageName).SandboxCacheBundleFilesRoot;
|
||||
_cachedDataFilePath = PathUtility.Combine(cacheRoot, folderName, CacheGUID, YooAssetSettings.CacheBundleDataFileName);
|
||||
}
|
||||
return _cachedDataFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存的信息文件路径
|
||||
/// </summary>
|
||||
private string _cachedInfoFilePath;
|
||||
public string CachedInfoFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cachedInfoFilePath) == false)
|
||||
return _cachedInfoFilePath;
|
||||
|
||||
string folderName = FileHash.Substring(0, 2);
|
||||
if (IsRawFile)
|
||||
{
|
||||
string cacheRoot = PersistentTools.GetPersistent(PackageName).SandboxCacheRawFilesRoot;
|
||||
_cachedInfoFilePath = PathUtility.Combine(cacheRoot, folderName, CacheGUID, YooAssetSettings.CacheBundleInfoFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
string cacheRoot = PersistentTools.GetPersistent(PackageName).SandboxCacheBundleFilesRoot;
|
||||
_cachedInfoFilePath = PathUtility.Combine(cacheRoot, folderName, CacheGUID, YooAssetSettings.CacheBundleInfoFileName);
|
||||
}
|
||||
return _cachedInfoFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临时的数据文件路径
|
||||
/// </summary>
|
||||
private string _tempDataFilePath;
|
||||
public string TempDataFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_tempDataFilePath) == false)
|
||||
return _tempDataFilePath;
|
||||
|
||||
_tempDataFilePath = $"{CachedDataFilePath}.temp";
|
||||
return _tempDataFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内置文件路径
|
||||
/// </summary>
|
||||
private string _streamingFilePath;
|
||||
public string StreamingFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_streamingFilePath) == false)
|
||||
return _streamingFilePath;
|
||||
|
||||
string root = PersistentTools.GetPersistent(PackageName).BuildinPackageRoot;
|
||||
_streamingFilePath = PathUtility.Combine(root, FileName);
|
||||
return _streamingFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// </summary>
|
||||
private string _fileName;
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_fileName))
|
||||
throw new Exception("Should never get here !");
|
||||
return _fileName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件后缀名
|
||||
/// </summary>
|
||||
private string _fileExtension;
|
||||
public string FileExtension
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_fileExtension))
|
||||
throw new Exception("Should never get here !");
|
||||
return _fileExtension;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PackageBundle()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析资源包
|
||||
/// </summary>
|
||||
public void ParseBundle(string packageName, int nameStype)
|
||||
{
|
||||
PackageName = packageName;
|
||||
_fileExtension = ManifestTools.GetRemoteBundleFileExtension(BundleName);
|
||||
_fileName = ManifestTools.GetRemoteBundleFileName(nameStype, BundleName, _fileExtension, FileHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含Tag
|
||||
/// </summary>
|
||||
public bool HasTag(string[] tags)
|
||||
{
|
||||
if (tags == null || tags.Length == 0)
|
||||
return false;
|
||||
if (Tags == null || Tags.Length == 0)
|
||||
return false;
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (Tags.Contains(tag))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含任意Tags
|
||||
/// </summary>
|
||||
public bool HasAnyTags()
|
||||
{
|
||||
if (Tags != null && Tags.Length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测资源包文件内容是否相同
|
||||
/// </summary>
|
||||
public bool Equals(PackageBundle otherBundle)
|
||||
{
|
||||
if (FileHash == otherBundle.FileHash)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70ff08c6c9b0f5e4c993ec4c91954467
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,355 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 清单文件
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
internal class PackageManifest
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件版本
|
||||
/// </summary>
|
||||
public string FileVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 启用可寻址资源定位
|
||||
/// </summary>
|
||||
public bool EnableAddressable;
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址大小写不敏感
|
||||
/// </summary>
|
||||
public bool LocationToLower;
|
||||
|
||||
/// <summary>
|
||||
/// 包含资源GUID数据
|
||||
/// </summary>
|
||||
public bool IncludeAssetGUID;
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称样式
|
||||
/// </summary>
|
||||
public int OutputNameStyle;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包裹的版本信息
|
||||
/// </summary>
|
||||
public string PackageVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 资源列表(主动收集的资源列表)
|
||||
/// </summary>
|
||||
public List<PackageAsset> AssetList = new List<PackageAsset>();
|
||||
|
||||
/// <summary>
|
||||
/// 资源包列表
|
||||
/// </summary>
|
||||
public List<PackageBundle> BundleList = new List<PackageBundle>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 资源包集合(提供BundleName获取PackageBundle)
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Dictionary<string, PackageBundle> BundleDic;
|
||||
|
||||
/// <summary>
|
||||
/// 资源映射集合(提供AssetPath获取PackageAsset)
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Dictionary<string, PackageAsset> AssetDic;
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径映射集合(提供Location获取AssetPath)
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Dictionary<string, string> AssetPathMapping1;
|
||||
|
||||
/// <summary>
|
||||
/// 资源路径映射集合(提供AssetGUID获取AssetPath)
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Dictionary<string, string> AssetPathMapping2;
|
||||
|
||||
/// <summary>
|
||||
/// 该资源清单所有文件的缓存GUID集合
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public HashSet<string> CacheGUIDs = new HashSet<string>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 尝试映射为资源路径
|
||||
/// </summary>
|
||||
public string TryMappingToAssetPath(string location)
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
return string.Empty;
|
||||
|
||||
if (LocationToLower)
|
||||
location = location.ToLower();
|
||||
|
||||
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
|
||||
return assetPath;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取主资源包
|
||||
/// 注意:传入的资源路径一定合法有效!
|
||||
/// </summary>
|
||||
public PackageBundle GetMainPackageBundle(string assetPath)
|
||||
{
|
||||
if (AssetDic.TryGetValue(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
int bundleID = packageAsset.BundleID;
|
||||
if (bundleID >= 0 && bundleID < BundleList.Count)
|
||||
{
|
||||
var packageBundle = BundleList[bundleID];
|
||||
return packageBundle;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {assetPath}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源依赖列表
|
||||
/// 注意:传入的资源路径一定合法有效!
|
||||
/// </summary>
|
||||
public PackageBundle[] GetAllDependencies(string assetPath)
|
||||
{
|
||||
if (AssetDic.TryGetValue(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
List<PackageBundle> result = new List<PackageBundle>(packageAsset.DependIDs.Length);
|
||||
foreach (var dependID in packageAsset.DependIDs)
|
||||
{
|
||||
if (dependID >= 0 && dependID < BundleList.Count)
|
||||
{
|
||||
var dependBundle = BundleList[dependID];
|
||||
result.Add(dependBundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Invalid bundle id : {dependID} Asset path : {assetPath}");
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包名称
|
||||
/// </summary>
|
||||
public string GetBundleName(int bundleID)
|
||||
{
|
||||
if (bundleID >= 0 && bundleID < BundleList.Count)
|
||||
{
|
||||
var packageBundle = BundleList[bundleID];
|
||||
return packageBundle.BundleName;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Invalid bundle id : {bundleID}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取包裹的资源
|
||||
/// </summary>
|
||||
public bool TryGetPackageAsset(string assetPath, out PackageAsset result)
|
||||
{
|
||||
return AssetDic.TryGetValue(assetPath, out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取包裹的资源包
|
||||
/// </summary>
|
||||
public bool TryGetPackageBundle(string bundleName, out PackageBundle result)
|
||||
{
|
||||
return BundleDic.TryGetValue(bundleName, out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含资源文件
|
||||
/// </summary>
|
||||
public bool IsIncludeBundleFile(string cacheGUID)
|
||||
{
|
||||
return CacheGUIDs.Contains(cacheGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源信息列表
|
||||
/// </summary>
|
||||
public AssetInfo[] GetAssetsInfoByTags(string[] tags)
|
||||
{
|
||||
List<AssetInfo> result = new List<AssetInfo>(100);
|
||||
foreach (var packageAsset in AssetList)
|
||||
{
|
||||
if (packageAsset.HasTag(tags))
|
||||
{
|
||||
AssetInfo assetInfo = new AssetInfo(packageAsset);
|
||||
result.Add(assetInfo);
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址转换为资源信息。
|
||||
/// </summary>
|
||||
/// <returns>如果转换失败会返回一个无效的资源信息类</returns>
|
||||
public AssetInfo ConvertLocationToAssetInfo(string location, System.Type assetType)
|
||||
{
|
||||
DebugCheckLocation(location);
|
||||
|
||||
string assetPath = ConvertLocationToAssetInfoMapping(location);
|
||||
if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
AssetInfo assetInfo = new AssetInfo(packageAsset, assetType);
|
||||
return assetInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error;
|
||||
if (string.IsNullOrEmpty(location))
|
||||
error = $"The location is null or empty !";
|
||||
else
|
||||
error = $"The location is invalid : {location}";
|
||||
AssetInfo assetInfo = new AssetInfo(error);
|
||||
return assetInfo;
|
||||
}
|
||||
}
|
||||
private string ConvertLocationToAssetInfoMapping(string location)
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
YooLogger.Error("Failed to mapping location to asset path, The location is null or empty.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (LocationToLower)
|
||||
location = location.ToLower();
|
||||
|
||||
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
|
||||
{
|
||||
return assetPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning($"Failed to mapping location to asset path : {location}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源GUID转换为资源信息。
|
||||
/// </summary>
|
||||
/// <returns>如果转换失败会返回一个无效的资源信息类</returns>
|
||||
public AssetInfo ConvertAssetGUIDToAssetInfo(string assetGUID, System.Type assetType)
|
||||
{
|
||||
if (IncludeAssetGUID == false)
|
||||
{
|
||||
YooLogger.Warning("Package manifest not include asset guid ! Please check asset bundle collector settings.");
|
||||
AssetInfo assetInfo = new AssetInfo("AssetGUID data is empty !");
|
||||
return assetInfo;
|
||||
}
|
||||
|
||||
string assetPath = ConvertAssetGUIDToAssetInfoMapping(assetGUID);
|
||||
if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
||||
{
|
||||
AssetInfo assetInfo = new AssetInfo(packageAsset, assetType);
|
||||
return assetInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
string error;
|
||||
if (string.IsNullOrEmpty(assetGUID))
|
||||
error = $"The assetGUID is null or empty !";
|
||||
else
|
||||
error = $"The assetGUID is invalid : {assetGUID}";
|
||||
AssetInfo assetInfo = new AssetInfo(error);
|
||||
return assetInfo;
|
||||
}
|
||||
}
|
||||
private string ConvertAssetGUIDToAssetInfoMapping(string assetGUID)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assetGUID))
|
||||
{
|
||||
YooLogger.Error("Failed to mapping assetGUID to asset path, The assetGUID is null or empty.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (AssetPathMapping2.TryGetValue(assetGUID, out string assetPath))
|
||||
{
|
||||
return assetPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning($"Failed to mapping assetGUID to asset path : {assetGUID}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包内的主资源列表
|
||||
/// </summary>
|
||||
public string[] GetBundleIncludeAssets(string assetPath)
|
||||
{
|
||||
List<string> assetList = new List<string>();
|
||||
if (TryGetPackageAsset(assetPath, out PackageAsset result))
|
||||
{
|
||||
foreach (var packageAsset in AssetList)
|
||||
{
|
||||
if (packageAsset.BundleID == result.BundleID)
|
||||
{
|
||||
assetList.Add(packageAsset.AssetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return assetList.ToArray();
|
||||
}
|
||||
|
||||
#region 调试方法
|
||||
[Conditional("DEBUG")]
|
||||
private void DebugCheckLocation(string location)
|
||||
{
|
||||
if (string.IsNullOrEmpty(location) == false)
|
||||
{
|
||||
// 检查路径末尾是否有空格
|
||||
int index = location.LastIndexOf(" ");
|
||||
if (index != -1)
|
||||
{
|
||||
if (location.Length == index + 1)
|
||||
YooLogger.Warning($"Found blank character in location : \"{location}\"");
|
||||
}
|
||||
|
||||
if (location.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0)
|
||||
YooLogger.Warning($"Found illegal character in location : \"{location}\"");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0bb3469358a90d41a3a4b284a3ddc8f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9d6cb1ce5d510645866ad7c122abfab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,45 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Reflection;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public static class EditorSimulateModeHelper
|
||||
{
|
||||
private static System.Type _classType;
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器下模拟构建清单
|
||||
/// </summary>
|
||||
public static string SimulateBuild(string packageName)
|
||||
{
|
||||
if (_classType == null)
|
||||
_classType = Assembly.Load("YooAsset.Editor").GetType("YooAsset.Editor.AssetBundleSimulateBuilder");
|
||||
|
||||
string manifestFilePath = (string)InvokePublicStaticMethod(_classType, "SimulateBuild", packageName);
|
||||
return manifestFilePath;
|
||||
}
|
||||
|
||||
private static object InvokePublicStaticMethod(System.Type type, string method, params object[] parameters)
|
||||
{
|
||||
var methodInfo = type.GetMethod(method, BindingFlags.Public | BindingFlags.Static);
|
||||
if (methodInfo == null)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"{type.FullName} not found method : {method}");
|
||||
return null;
|
||||
}
|
||||
return methodInfo.Invoke(null, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace YooAsset
|
||||
{
|
||||
public static class EditorSimulateModeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 编辑器下模拟构建清单
|
||||
/// </summary>
|
||||
public static string SimulateBuild(string packageName) { throw new System.Exception("Only support in unity editor !"); }
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b09fe4b7aa2d2143bc538976541b039
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class EditorSimulateModeImpl : IPlayModeServices, IBundleServices
|
||||
{
|
||||
private PackageManifest _activeManifest;
|
||||
|
||||
/// <summary>
|
||||
/// 异步初始化
|
||||
/// </summary>
|
||||
public InitializationOperation InitializeAsync(string simulateManifestFilePath)
|
||||
{
|
||||
var operation = new EditorSimulateModeInitializationOperation(this, simulateManifestFilePath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
#region IPlayModeServices接口
|
||||
public PackageManifest ActiveManifest
|
||||
{
|
||||
set
|
||||
{
|
||||
_activeManifest = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return _activeManifest;
|
||||
}
|
||||
}
|
||||
public void FlushManifestVersionFile()
|
||||
{
|
||||
}
|
||||
|
||||
UpdatePackageVersionOperation IPlayModeServices.UpdatePackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdatePackageVersionOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
UpdatePackageManifestOperation IPlayModeServices.UpdatePackageManifestAsync(string packageVersion, bool autoSaveVersion, int timeout)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdatePackageManifestOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
PreDownloadContentOperation IPlayModeServices.PreDownloadContentAsync(string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new EditorPlayModePreDownloadContentOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByTags(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByPaths(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByAll(int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceUnpackerOperation.CreateEmptyUnpacker(upackingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByTags(string[] tags, int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceUnpackerOperation.CreateEmptyUnpacker(upackingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IBundleServices接口
|
||||
private BundleInfo CreateBundleInfo(PackageBundle packageBundle, AssetInfo assetInfo)
|
||||
{
|
||||
if (packageBundle == null)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromEditor);
|
||||
bundleInfo.IncludeAssets = _activeManifest.GetBundleIncludeAssets(assetInfo.AssetPath);
|
||||
return bundleInfo;
|
||||
}
|
||||
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
return CreateBundleInfo(packageBundle, assetInfo);
|
||||
}
|
||||
BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
List<BundleInfo> result = new List<BundleInfo>(depends.Length);
|
||||
foreach (var packageBundle in depends)
|
||||
{
|
||||
BundleInfo bundleInfo = CreateBundleInfo(packageBundle, assetInfo);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
string IBundleServices.GetBundleName(int bundleID)
|
||||
{
|
||||
return _activeManifest.GetBundleName(bundleID);
|
||||
}
|
||||
bool IBundleServices.IsServicesValid()
|
||||
{
|
||||
return _activeManifest != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fb1b9a2a91f1af4a86acfcfac424e0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,354 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class HostPlayModeImpl : IPlayModeServices, IBundleServices
|
||||
{
|
||||
private PackageManifest _activeManifest;
|
||||
|
||||
// 参数相关
|
||||
private string _packageName;
|
||||
private IBuildinQueryServices _buildinQueryServices;
|
||||
private IDeliveryQueryServices _deliveryQueryServices;
|
||||
private IRemoteServices _remoteServices;
|
||||
|
||||
public IRemoteServices RemoteServices
|
||||
{
|
||||
get { return _remoteServices; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步初始化
|
||||
/// </summary>
|
||||
public InitializationOperation InitializeAsync(string packageName, IBuildinQueryServices buildinQueryServices, IDeliveryQueryServices deliveryQueryServices, IRemoteServices remoteServices)
|
||||
{
|
||||
_packageName = packageName;
|
||||
_buildinQueryServices = buildinQueryServices;
|
||||
_deliveryQueryServices = deliveryQueryServices;
|
||||
_remoteServices = remoteServices;
|
||||
|
||||
var operation = new HostPlayModeInitializationOperation(this, packageName);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
// 下载相关
|
||||
private List<BundleInfo> ConvertToDownloadList(List<PackageBundle> downloadList)
|
||||
{
|
||||
List<BundleInfo> result = new List<BundleInfo>(downloadList.Count);
|
||||
foreach (var packageBundle in downloadList)
|
||||
{
|
||||
var bundleInfo = ConvertToDownloadInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private BundleInfo ConvertToDownloadInfo(PackageBundle packageBundle)
|
||||
{
|
||||
string remoteMainURL = _remoteServices.GetRemoteMainURL(packageBundle.FileName);
|
||||
string remoteFallbackURL = _remoteServices.GetRemoteFallbackURL(packageBundle.FileName);
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromRemote, remoteMainURL, remoteFallbackURL);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
private bool IsBuildinPackageBundle(PackageBundle packageBundle)
|
||||
{
|
||||
return _buildinQueryServices.QueryStreamingAssets(_packageName, packageBundle.FileName);
|
||||
}
|
||||
private bool IsCachedPackageBundle(PackageBundle packageBundle)
|
||||
{
|
||||
return CacheSystem.IsCached(packageBundle.PackageName, packageBundle.CacheGUID);
|
||||
}
|
||||
private bool IsDeliveryPackageBundle(PackageBundle packageBundle)
|
||||
{
|
||||
return _deliveryQueryServices.QueryDeliveryFiles(_packageName, packageBundle.FileName);
|
||||
}
|
||||
private DeliveryFileInfo GetDeiveryFileInfo(PackageBundle packageBundle)
|
||||
{
|
||||
return _deliveryQueryServices.GetDeliveryFileInfo(_packageName, packageBundle.FileName);
|
||||
}
|
||||
|
||||
#region IPlayModeServices接口
|
||||
public PackageManifest ActiveManifest
|
||||
{
|
||||
set
|
||||
{
|
||||
_activeManifest = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return _activeManifest;
|
||||
}
|
||||
}
|
||||
public void FlushManifestVersionFile()
|
||||
{
|
||||
if (_activeManifest != null)
|
||||
{
|
||||
PersistentTools.GetPersistent(_packageName).SaveSandboxPackageVersionFile(_activeManifest.PackageVersion);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePackageVersionOperation IPlayModeServices.UpdatePackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModeUpdatePackageVersionOperation(this, _packageName, appendTimeTicks, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
UpdatePackageManifestOperation IPlayModeServices.UpdatePackageManifestAsync(string packageVersion, bool autoSaveVersion, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModeUpdatePackageManifestOperation(this, _packageName, packageVersion, autoSaveVersion, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
PreDownloadContentOperation IPlayModeServices.PreDownloadContentAsync(string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModePreDownloadContentOperation(this, _packageName, packageVersion, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByAll(_activeManifest);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByAll(PackageManifest manifest)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略分发文件
|
||||
if (IsDeliveryPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByTags(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByTags(_activeManifest, tags);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByTags(PackageManifest manifest, string[] tags)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略分发文件
|
||||
if (IsDeliveryPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 如果未带任何标记,则统一下载
|
||||
if (packageBundle.HasAnyTags() == false)
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 查询DLC资源
|
||||
if (packageBundle.HasTag(tags))
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByPaths(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByPaths(_activeManifest, assetInfos);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByPaths(PackageManifest manifest, AssetInfo[] assetInfos)
|
||||
{
|
||||
// 获取资源对象的资源包和所有依赖资源包
|
||||
List<PackageBundle> checkList = new List<PackageBundle>();
|
||||
foreach (var assetInfo in assetInfos)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Warning(assetInfo.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
PackageBundle mainBundle = manifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
if (checkList.Contains(mainBundle) == false)
|
||||
checkList.Add(mainBundle);
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
PackageBundle[] dependBundles = manifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
foreach (var dependBundle in dependBundles)
|
||||
{
|
||||
if (checkList.Contains(dependBundle) == false)
|
||||
checkList.Add(dependBundle);
|
||||
}
|
||||
}
|
||||
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in checkList)
|
||||
{
|
||||
// 忽略分发文件
|
||||
if (IsDeliveryPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByAll(int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> unpcakList = GetUnpackListByAll(_activeManifest);
|
||||
var operation = new ResourceUnpackerOperation(unpcakList, upackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
private List<BundleInfo> GetUnpackListByAll(PackageManifest manifest)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
}
|
||||
|
||||
return ManifestTools.ConvertToUnpackInfos(downloadList);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByTags(string[] tags, int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> unpcakList = GetUnpackListByTags(_activeManifest, tags);
|
||||
var operation = new ResourceUnpackerOperation(unpcakList, upackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
private List<BundleInfo> GetUnpackListByTags(PackageManifest manifest, string[] tags)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 查询DLC资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
{
|
||||
if (packageBundle.HasTag(tags))
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ManifestTools.ConvertToUnpackInfos(downloadList);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IBundleServices接口
|
||||
private BundleInfo CreateBundleInfo(PackageBundle packageBundle)
|
||||
{
|
||||
if (packageBundle == null)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 查询分发资源
|
||||
if (IsDeliveryPackageBundle(packageBundle))
|
||||
{
|
||||
DeliveryFileInfo deliveryFileInfo = GetDeiveryFileInfo(packageBundle);
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromDelivery, deliveryFileInfo.DeliveryFilePath, deliveryFileInfo.DeliveryFileOffset);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 查询沙盒资源
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromCache);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 查询APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromStreaming);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 从服务端下载
|
||||
return ConvertToDownloadInfo(packageBundle);
|
||||
}
|
||||
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
return CreateBundleInfo(packageBundle);
|
||||
}
|
||||
BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
List<BundleInfo> result = new List<BundleInfo>(depends.Length);
|
||||
foreach (var packageBundle in depends)
|
||||
{
|
||||
BundleInfo bundleInfo = CreateBundleInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
string IBundleServices.GetBundleName(int bundleID)
|
||||
{
|
||||
return _activeManifest.GetBundleName(bundleID);
|
||||
}
|
||||
bool IBundleServices.IsServicesValid()
|
||||
{
|
||||
return _activeManifest != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84c10fd3507a1c24a9043aebb72db5f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class OfflinePlayModeImpl : IPlayModeServices, IBundleServices
|
||||
{
|
||||
private PackageManifest _activeManifest;
|
||||
|
||||
/// <summary>
|
||||
/// 异步初始化
|
||||
/// </summary>
|
||||
public InitializationOperation InitializeAsync(string packageName)
|
||||
{
|
||||
var operation = new OfflinePlayModeInitializationOperation(this, packageName);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
private bool IsCachedPackageBundle(PackageBundle packageBundle)
|
||||
{
|
||||
return CacheSystem.IsCached(packageBundle.PackageName, packageBundle.CacheGUID);
|
||||
}
|
||||
|
||||
#region IPlayModeServices接口
|
||||
public PackageManifest ActiveManifest
|
||||
{
|
||||
set
|
||||
{
|
||||
_activeManifest = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return _activeManifest;
|
||||
}
|
||||
}
|
||||
public void FlushManifestVersionFile()
|
||||
{
|
||||
}
|
||||
|
||||
UpdatePackageVersionOperation IPlayModeServices.UpdatePackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdatePackageVersionOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
UpdatePackageManifestOperation IPlayModeServices.UpdatePackageManifestAsync(string packageVersion, bool autoSaveVersion, int timeout)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdatePackageManifestOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
PreDownloadContentOperation IPlayModeServices.PreDownloadContentAsync(string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new OfflinePlayModePreDownloadContentOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByTags(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByPaths(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceDownloaderOperation.CreateEmptyDownloader(downloadingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByAll(int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> unpcakList = GetUnpackListByAll(_activeManifest);
|
||||
var operation = new ResourceUnpackerOperation(unpcakList, upackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
private List<BundleInfo> GetUnpackListByAll(PackageManifest manifest)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
|
||||
return ManifestTools.ConvertToUnpackInfos(downloadList);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByTags(string[] tags, int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> unpcakList = GetUnpackListByTags(_activeManifest, tags);
|
||||
var operation = new ResourceUnpackerOperation(unpcakList, upackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
private List<BundleInfo> GetUnpackListByTags(PackageManifest manifest, string[] tags)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (IsCachedPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 查询DLC资源
|
||||
if (packageBundle.HasTag(tags))
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
}
|
||||
|
||||
return ManifestTools.ConvertToUnpackInfos(downloadList);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IBundleServices接口
|
||||
private BundleInfo CreateBundleInfo(PackageBundle packageBundle)
|
||||
{
|
||||
if (packageBundle == null)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 查询沙盒资源
|
||||
if (CacheSystem.IsCached(packageBundle.PackageName, packageBundle.CacheGUID))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromCache);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 查询APP资源
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromStreaming);
|
||||
return bundleInfo;
|
||||
}
|
||||
}
|
||||
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
return CreateBundleInfo(packageBundle);
|
||||
}
|
||||
BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
List<BundleInfo> result = new List<BundleInfo>(depends.Length);
|
||||
foreach (var packageBundle in depends)
|
||||
{
|
||||
BundleInfo bundleInfo = CreateBundleInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
string IBundleServices.GetBundleName(int bundleID)
|
||||
{
|
||||
return _activeManifest.GetBundleName(bundleID);
|
||||
}
|
||||
bool IBundleServices.IsServicesValid()
|
||||
{
|
||||
return _activeManifest != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc10550f17aaeb14795135a51444de1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,254 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class WebPlayModeImpl : IPlayModeServices, IBundleServices
|
||||
{
|
||||
private PackageManifest _activeManifest;
|
||||
|
||||
// 参数相关
|
||||
private string _packageName;
|
||||
private IBuildinQueryServices _buildinQueryServices;
|
||||
private IRemoteServices _remoteServices;
|
||||
|
||||
public IRemoteServices RemoteServices
|
||||
{
|
||||
get { return _remoteServices; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步初始化
|
||||
/// </summary>
|
||||
public InitializationOperation InitializeAsync(string packageName, IBuildinQueryServices buildinQueryServices, IRemoteServices remoteServices)
|
||||
{
|
||||
_packageName = packageName;
|
||||
_buildinQueryServices = buildinQueryServices;
|
||||
_remoteServices = remoteServices;
|
||||
|
||||
var operation = new WebPlayModeInitializationOperation(this, packageName);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
// 下载相关
|
||||
private List<BundleInfo> ConvertToDownloadList(List<PackageBundle> downloadList)
|
||||
{
|
||||
List<BundleInfo> result = new List<BundleInfo>(downloadList.Count);
|
||||
foreach (var packageBundle in downloadList)
|
||||
{
|
||||
var bundleInfo = ConvertToDownloadInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private BundleInfo ConvertToDownloadInfo(PackageBundle packageBundle)
|
||||
{
|
||||
string remoteMainURL = _remoteServices.GetRemoteMainURL(packageBundle.FileName);
|
||||
string remoteFallbackURL = _remoteServices.GetRemoteFallbackURL(packageBundle.FileName);
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromRemote, remoteMainURL, remoteFallbackURL);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
private bool IsBuildinPackageBundle(PackageBundle packageBundle)
|
||||
{
|
||||
return _buildinQueryServices.QueryStreamingAssets(_packageName, packageBundle.FileName);
|
||||
}
|
||||
|
||||
#region IPlayModeServices接口
|
||||
public PackageManifest ActiveManifest
|
||||
{
|
||||
set
|
||||
{
|
||||
_activeManifest = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return _activeManifest;
|
||||
}
|
||||
}
|
||||
public void FlushManifestVersionFile()
|
||||
{
|
||||
}
|
||||
|
||||
UpdatePackageVersionOperation IPlayModeServices.UpdatePackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||
{
|
||||
var operation = new WebPlayModeUpdatePackageVersionOperation(this, _packageName, appendTimeTicks, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
UpdatePackageManifestOperation IPlayModeServices.UpdatePackageManifestAsync(string packageVersion, bool autoSaveVersion, int timeout)
|
||||
{
|
||||
var operation = new WebPlayModeUpdatePackageManifestOperation(this, _packageName, packageVersion, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
PreDownloadContentOperation IPlayModeServices.PreDownloadContentAsync(string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new WebPlayModePreDownloadContentOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByAll(_activeManifest);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByAll(PackageManifest manifest)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByTags(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByTags(_activeManifest, tags);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByTags(PackageManifest manifest, string[] tags)
|
||||
{
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
// 如果未带任何标记,则统一下载
|
||||
if (packageBundle.HasAnyTags() == false)
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 查询DLC资源
|
||||
if (packageBundle.HasTag(tags))
|
||||
{
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceDownloaderOperation IPlayModeServices.CreateResourceDownloaderByPaths(AssetInfo[] assetInfos, int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
List<BundleInfo> downloadList = GetDownloadListByPaths(_activeManifest, assetInfos);
|
||||
var operation = new ResourceDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
public List<BundleInfo> GetDownloadListByPaths(PackageManifest manifest, AssetInfo[] assetInfos)
|
||||
{
|
||||
// 获取资源对象的资源包和所有依赖资源包
|
||||
List<PackageBundle> checkList = new List<PackageBundle>();
|
||||
foreach (var assetInfo in assetInfos)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Warning(assetInfo.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
PackageBundle mainBundle = manifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
if (checkList.Contains(mainBundle) == false)
|
||||
checkList.Add(mainBundle);
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
PackageBundle[] dependBundles = manifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
foreach (var dependBundle in dependBundles)
|
||||
{
|
||||
if (checkList.Contains(dependBundle) == false)
|
||||
checkList.Add(dependBundle);
|
||||
}
|
||||
}
|
||||
|
||||
List<PackageBundle> downloadList = new List<PackageBundle>(1000);
|
||||
foreach (var packageBundle in checkList)
|
||||
{
|
||||
// 忽略APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
continue;
|
||||
|
||||
downloadList.Add(packageBundle);
|
||||
}
|
||||
|
||||
return ConvertToDownloadList(downloadList);
|
||||
}
|
||||
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByAll(int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceUnpackerOperation.CreateEmptyUnpacker(upackingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
ResourceUnpackerOperation IPlayModeServices.CreateResourceUnpackerByTags(string[] tags, int upackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
return ResourceUnpackerOperation.CreateEmptyUnpacker(upackingMaxNumber, failedTryAgain, timeout);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IBundleServices接口
|
||||
private BundleInfo CreateBundleInfo(PackageBundle packageBundle)
|
||||
{
|
||||
if (packageBundle == null)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 查询APP资源
|
||||
if (IsBuildinPackageBundle(packageBundle))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(packageBundle, BundleInfo.ELoadMode.LoadFromStreaming);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 从服务端下载
|
||||
return ConvertToDownloadInfo(packageBundle);
|
||||
}
|
||||
BundleInfo IBundleServices.GetBundleInfo(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath);
|
||||
return CreateBundleInfo(packageBundle);
|
||||
}
|
||||
BundleInfo[] IBundleServices.GetAllDependBundleInfos(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
// 注意:如果清单里未找到资源包会抛出异常!
|
||||
var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath);
|
||||
List<BundleInfo> result = new List<BundleInfo>(depends.Length);
|
||||
foreach (var packageBundle in depends)
|
||||
{
|
||||
BundleInfo bundleInfo = CreateBundleInfo(packageBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
string IBundleServices.GetBundleName(int bundleID)
|
||||
{
|
||||
return _activeManifest.GetBundleName(bundleID);
|
||||
}
|
||||
bool IBundleServices.IsServicesValid()
|
||||
{
|
||||
return _activeManifest != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa7d8823ee040534db067e6e2c254267
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fcda791b973f5b4499e8bd3ede91312
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user