using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; namespace YooAsset { /// /// 初始化操作 /// public abstract class InitializationOperation : AsyncOperationBase { public string PackageVersion { protected set; get; } } /// /// 编辑器下模拟模式的初始化操作 /// 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 InternalOnStart() { _steps = ESteps.LoadEditorManifest; } internal override void InternalOnUpdate() { if (_steps == ESteps.LoadEditorManifest) { if (_loadEditorManifestOp == null) { _loadEditorManifestOp = new LoadEditorManifestOperation(_impl.PackageName, _simulateManifestFilePath); OperationSystem.StartOperation(_impl.PackageName, _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; } } } } /// /// 离线运行模式的初始化操作 /// internal sealed class OfflinePlayModeInitializationOperation : InitializationOperation { private enum ESteps { None, QueryBuildinPackageVersion, LoadBuildinManifest, PackageCaching, Done, } private readonly OfflinePlayModeImpl _impl; private QueryBuildinPackageVersionOperation _queryBuildinPackageVersionOp; private LoadBuildinManifestOperation _loadBuildinManifestOp; private PackageCachingOperation _cachingOperation; private ESteps _steps = ESteps.None; internal OfflinePlayModeInitializationOperation(OfflinePlayModeImpl impl) { _impl = impl; } internal override void InternalOnStart() { _steps = ESteps.QueryBuildinPackageVersion; } internal override void InternalOnUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; if (_steps == ESteps.QueryBuildinPackageVersion) { if (_queryBuildinPackageVersionOp == null) { _queryBuildinPackageVersionOp = new QueryBuildinPackageVersionOperation(_impl.Persistent); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _queryBuildinPackageVersionOp.PackageVersion); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _impl.Cache); OperationSystem.StartOperation(_impl.PackageName, _cachingOperation); } Progress = _cachingOperation.Progress; if (_cachingOperation.IsDone) { _steps = ESteps.Done; Status = EOperationStatus.Succeed; } } } } /// /// 联机运行模式的初始化操作 /// 注意:优先从沙盒里加载清单,如果沙盒里不存在就尝试把内置清单拷贝到沙盒并加载该清单。 /// internal sealed class HostPlayModeInitializationOperation : InitializationOperation { private enum ESteps { None, CheckAppFootPrint, QueryCachePackageVersion, TryLoadCacheManifest, QueryBuildinPackageVersion, UnpackBuildinManifest, LoadBuildinManifest, PackageCaching, Done, } private readonly HostPlayModeImpl _impl; 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) { _impl = impl; } internal override void InternalOnStart() { _steps = ESteps.CheckAppFootPrint; } internal override void InternalOnUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; if (_steps == ESteps.CheckAppFootPrint) { var appFootPrint = new AppFootPrint(_impl.Persistent); appFootPrint.Load(_impl.PackageName); // 如果水印发生变化,则说明覆盖安装后首次打开游戏 if (appFootPrint.IsDirty()) { _impl.Persistent.DeleteSandboxManifestFilesFolder(); appFootPrint.Coverage(_impl.PackageName); YooLogger.Log("Delete manifest files when application foot print dirty !"); } _steps = ESteps.QueryCachePackageVersion; } if (_steps == ESteps.QueryCachePackageVersion) { if (_queryCachePackageVersionOp == null) { _queryCachePackageVersionOp = new QueryCachePackageVersionOperation(_impl.Persistent); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _queryCachePackageVersionOp.PackageVersion); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _queryBuildinPackageVersionOp.PackageVersion); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _queryBuildinPackageVersionOp.PackageVersion); OperationSystem.StartOperation(_impl.PackageName, _loadBuildinManifestOp); } Progress = _loadBuildinManifestOp.Progress; if (_loadBuildinManifestOp.IsDone == false) return; if (_loadBuildinManifestOp.Status == EOperationStatus.Succeed) { PackageVersion = _loadBuildinManifestOp.Manifest.PackageVersion; _impl.ActiveManifest = _loadBuildinManifestOp.Manifest; _impl.FlushManifestVersionFile(); //注意:解压内置清单并加载成功后保存该清单版本。 _steps = ESteps.PackageCaching; } else { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = _loadBuildinManifestOp.Error; } } if (_steps == ESteps.PackageCaching) { if (_cachingOperation == null) { _cachingOperation = new PackageCachingOperation(_impl.Persistent, _impl.Cache); OperationSystem.StartOperation(_impl.PackageName, _cachingOperation); } Progress = _cachingOperation.Progress; if (_cachingOperation.IsDone) { _steps = ESteps.Done; Status = EOperationStatus.Succeed; } } } } /// /// WebGL运行模式的初始化操作 /// internal sealed class WebPlayModeInitializationOperation : InitializationOperation { private enum ESteps { None, QueryWebPackageVersion, LoadWebManifest, Done, } private readonly WebPlayModeImpl _impl; private QueryBuildinPackageVersionOperation _queryWebPackageVersionOp; private LoadBuildinManifestOperation _loadWebManifestOp; private ESteps _steps = ESteps.None; internal WebPlayModeInitializationOperation(WebPlayModeImpl impl) { _impl = impl; } internal override void InternalOnStart() { _steps = ESteps.QueryWebPackageVersion; } internal override void InternalOnUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; if (_steps == ESteps.QueryWebPackageVersion) { if (_queryWebPackageVersionOp == null) { _queryWebPackageVersionOp = new QueryBuildinPackageVersionOperation(_impl.Persistent); OperationSystem.StartOperation(_impl.PackageName, _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(_impl.Persistent, _queryWebPackageVersionOp.PackageVersion); OperationSystem.StartOperation(_impl.PackageName, _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; } } } } /// /// 应用程序水印 /// internal class AppFootPrint { private PersistentManager _persistent; private string _footPrint; public AppFootPrint(PersistentManager persistent) { _persistent = persistent; } /// /// 读取应用程序水印 /// public void Load(string packageName) { string footPrintFilePath = _persistent.SandboxAppFootPrintFilePath; if (File.Exists(footPrintFilePath)) { _footPrint = FileUtility.ReadAllText(footPrintFilePath); } else { Coverage(packageName); } } /// /// 检测水印是否发生变化 /// public bool IsDirty() { #if UNITY_EDITOR return _footPrint != Application.version; #else return _footPrint != Application.buildGUID; #endif } /// /// 覆盖掉水印 /// public void Coverage(string packageName) { #if UNITY_EDITOR _footPrint = Application.version; #else _footPrint = Application.buildGUID; #endif string footPrintFilePath = _persistent.SandboxAppFootPrintFilePath; FileUtility.WriteAllText(footPrintFilePath, _footPrint); YooLogger.Log($"Save application foot print : {_footPrint}"); } } }