/// <summary> /// 修复客户端 /// </summary> public void FixClient() { // 清空缓存 PatchHelper.ClearSandbox(); // 重启游戏 #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else Application.Quit(); #endif }
/// <summary> /// 读取缓存文件 /// </summary> public static PatchCache LoadCache() { if (PatchHelper.CheckSandboxCacheFileExist() == false) { return(new PatchCache()); } MotionLog.Log("Load cache from disk."); string filePath = PatchHelper.GetSandboxCacheFilePath(); string jsonData = FileUtility.ReadFile(filePath); return(JsonUtility.FromJson <PatchCache>(jsonData)); }
public IEnumerator Download() { // 获取最新的游戏版本号 { string url = _patcher.GetWebServerIP(); string post = _patcher.GetWebPostData(); PatchHelper.Log(ELogLevel.Log, $"Request game version : {url} : {post}"); WebPostRequest download = new WebPostRequest(url, post); yield return(download.DownLoad()); //Check fatal if (download.States != EWebRequestStates.Success) { download.Dispose(); PatchEventDispatcher.SendGameVersionRequestFailedMsg(); yield break; } string responseData = download.GetResponse(); _patcher.ParseResponseData(responseData); download.Dispose(); } int newResourceVersion = _patcher.RequestedResourceVersion; int oldResourceVersion = _patcher.SandboxPatchManifest.Version; // 检测强更安装包 string appInstallURL = _patcher.GetForceInstallAppURL(); if (string.IsNullOrEmpty(appInstallURL) == false) { PatchHelper.Log(ELogLevel.Log, $"Found new APP can be install : {_patcher.GameVersion.ToString()}"); PatchEventDispatcher.SendFoundForceInstallAPPMsg(_patcher.GameVersion.ToString(), appInstallURL); yield break; } // 检测资源版本是否变化 if (newResourceVersion == oldResourceVersion) { PatchHelper.Log(ELogLevel.Log, $"Resource version is not change."); _patcher.Switch(EPatchStates.DownloadOver.ToString()); } else { PatchHelper.Log(ELogLevel.Log, $"Resource version is change : {oldResourceVersion} -> {newResourceVersion}"); _patcher.SwitchNext(); } }
private WebFileRequest CreateDownloader(PatchBundle element) { // 注意:资源版本号只用于确定下载路径 string url = _patcher.GetWebDownloadURL(element.Version.ToString(), element.Hash); string savePath = PatchHelper.MakeSandboxCacheFilePath(element.Hash); FileUtility.CreateFileDirectory(savePath); // 创建下载器 MotionLog.Log($"Beginning to download web file : {url}"); WebFileRequest download = new WebFileRequest(url, savePath); download.UserData = element; download.DownLoad(); return(download); }
private WebFileRequest CreateDownloader(PatchBundle patchBundle) { // 注意:资源版本号只用于确定下载路径 string mainURL = _patcherMgr.GetPatchDownloadURL(patchBundle.Version, patchBundle.Hash); string fallbackURL = _patcherMgr.GetPatchDownloadFallbackURL(patchBundle.Version, patchBundle.Hash); string savePath = PatchHelper.MakeSandboxCacheFilePath(patchBundle.Hash); FileUtility.CreateFileDirectory(savePath); // 创建下载器 MotionLog.Log($"Beginning to download web file : {patchBundle.BundleName} URL : {mainURL}"); WebFileRequest download = WebFileSystem.GetWebFileRequest(mainURL, fallbackURL, savePath, _failedTryAgain); download.UserData = patchBundle; return(download); }
void IFsmNode.OnEnter() { PatchEventDispatcher.SendPatchStatesChangeMsg(EPatchStates.ParseSandboxPatchManifest); // 读取并解析沙盒内的补丁清单 if (PatchHelper.CheckSandboxPatchManifestFileExist()) { string filePath = AssetPathHelper.MakePersistentLoadPath(PatchDefine.PatchManifestFileName); string fileContent = PatchHelper.ReadFile(filePath); PatchHelper.Log(ELogLevel.Log, $"Parse sandbox patch file."); _patcher.ParseSandboxPatchManifest(fileContent); } else { _patcher.ParseSandboxPatchManifest(_patcher.AppPatchManifest); } _patcher.SwitchNext(); }
private IEnumerator DownLoad() { // 解析APP里的补丁清单 string filePath = AssetPathHelper.MakeStreamingLoadPath(PatchDefine.PatchManifestFileName); string url = AssetPathHelper.ConvertToWWWPath(filePath); WebDataRequest downloader = new WebDataRequest(url); yield return(downloader.DownLoad()); if (downloader.States == EWebRequestStates.Success) { PatchHelper.Log(ELogLevel.Log, "Parse app patch manifest."); _patcher.ParseAppPatchManifest(downloader.GetText()); downloader.Dispose(); _patcher.SwitchNext(); } else { throw new System.Exception($"Fatal error : Failed download file : {url}"); } }
private bool CheckContentIntegrity(string md5, uint crc32, long size) { string filePath = PatchHelper.MakeSandboxCacheFilePath(md5); if (File.Exists(filePath) == false) { return(false); } // 校验沙盒里的补丁文件 if (_verifyLevel == EVerifyLevel.Size) { long fileSize = FileUtility.GetFileSize(filePath); if (fileSize == size) { return(true); } } else if (_verifyLevel == EVerifyLevel.MD5) { string fileHash = HashUtility.FileMD5(filePath); if (fileHash == md5) { return(true); } } else if (_verifyLevel == EVerifyLevel.CRC32) { uint fileHash = HashUtility.FileCRC32(filePath); if (fileHash == crc32) { return(true); } } else { throw new NotImplementedException(_verifyLevel.ToString()); } return(false); }
string IBundleServices.GetAssetBundleLoadPath(string manifestPath) { PatchManifest patchManifest; if (_patcher.WebPatchManifest != null) { patchManifest = _patcher.WebPatchManifest; } else { patchManifest = _patcher.SandboxPatchManifest; } // 尝试获取变体资源清单路径 manifestPath = _variantCollector.TryGetVariantManifestPath(manifestPath); // 注意:可能从APP内加载,也可能从沙盒内加载 PatchElement element; if (patchManifest.Elements.TryGetValue(manifestPath, out element)) { // 先查询APP内的资源 PatchElement appElement; if (_patcher.AppPatchManifest.Elements.TryGetValue(manifestPath, out appElement)) { if (appElement.MD5 == element.MD5) { return(AssetPathHelper.MakeStreamingLoadPath(manifestPath)); } } // 如果APP里不存在或者MD5不匹配,则从沙盒里加载 return(AssetPathHelper.MakePersistentLoadPath(manifestPath)); } else { PatchHelper.Log(ELogLevel.Warning, $"Not found element in patch manifest : {manifestPath}"); return(AssetPathHelper.MakeStreamingLoadPath(manifestPath)); } }
private IEnumerator Download() { // 从网络上解析最新的补丁清单 int newResourceVersion = _patcher.RequestedResourceVersion; string url = _patcher.GetWebDownloadURL(newResourceVersion.ToString(), PatchDefine.PatchManifestFileName); WebDataRequest download = new WebDataRequest(url); yield return(download.DownLoad()); // Check fatal if (download.States != EWebRequestStates.Success) { download.Dispose(); PatchEventDispatcher.SendWebPatchManifestDownloadFailedMsg(); yield break; } PatchHelper.Log(ELogLevel.Log, $"Parse web patch manifest."); _patcher.ParseWebPatchManifest(download.GetText()); download.Dispose(); _patcher.SwitchNext(); }
/// <summary> /// 获取AssetBundle的加载信息 /// </summary> public AssetBundleInfo GetAssetBundleInfo(string bundleName) { if (_localPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle patchBundle)) { // 查询APP资源 if (_appPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle appPatchBundle)) { if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash) { string appLoadPath = AssetPathHelper.MakeStreamingLoadPath(appPatchBundle.Hash); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, appLoadPath, appPatchBundle.Version, appPatchBundle.IsEncrypted); return(bundleInfo); } } // 查询缓存资源 // 注意:如果沙盒内缓存文件不存在,那么将会从服务器下载 string sandboxLoadPath = PatchHelper.MakeSandboxCacheFilePath(patchBundle.Hash); if (_cache.Contains(patchBundle.Hash)) { AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, sandboxLoadPath, patchBundle.Version, patchBundle.IsEncrypted); return(bundleInfo); } else { string remoteURL = GetPatchDownloadURL(patchBundle.Version, patchBundle.Hash); string remoteFallbackURL = GetPatchDownloadFallbackURL(patchBundle.Version, patchBundle.Hash); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, sandboxLoadPath, remoteURL, remoteFallbackURL, patchBundle.Version, patchBundle.IsEncrypted); return(bundleInfo); } } else { MotionLog.Warning($"Not found bundle in patch manifest : {bundleName}"); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, string.Empty); return(bundleInfo); } }
private IEnumerator Download() { // 注意:等所有文件下载完毕后,下载并替换补丁清单 int newResourceVersion = _patcher.RequestedResourceVersion; string url = _patcher.GetWebDownloadURL(newResourceVersion.ToString(), PatchDefine.PatchManifestFileName); string savePath = AssetPathHelper.MakePersistentLoadPath(PatchDefine.PatchManifestFileName); WebFileRequest download = new WebFileRequest(url, savePath); yield return(download.DownLoad()); if (download.States != EWebRequestStates.Success) { download.Dispose(); PatchEventDispatcher.SendWebPatchManifestDownloadFailedMsg(); yield break; } else { PatchHelper.Log(ELogLevel.Log, "Web patch manifest is download."); download.Dispose(); _patcher.SwitchNext(); } }
/// <summary> /// 获取AssetBundle的加载信息 /// </summary> public AssetBundleInfo GetAssetBundleInfo(string bundleName) { if (_localPatchManifest.Elements.TryGetValue(bundleName, out PatchElement element)) { // 查询内置资源 if (_appPatchManifest.Elements.TryGetValue(bundleName, out PatchElement appElement)) { if (appElement.IsDLC() == false && appElement.MD5 == element.MD5) { string appLoadPath = AssetPathHelper.MakeStreamingLoadPath(appElement.MD5); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, appLoadPath, string.Empty, appElement.Version, appElement.IsEncrypted); return(bundleInfo); } } // 查询缓存资源 // 注意:如果沙盒内缓存文件不存在,那么将会从服务器下载 string sandboxLoadPath = PatchHelper.MakeSandboxCacheFilePath(element.MD5); if (_cache.Contains(element.MD5)) { AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, sandboxLoadPath, string.Empty, element.Version, element.IsEncrypted); return(bundleInfo); } else { string remoteURL = GetWebDownloadURL(element.Version.ToString(), element.MD5); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, sandboxLoadPath, remoteURL, element.Version, element.IsEncrypted); return(bundleInfo); } } else { MotionLog.Warning($"Not found element in patch manifest : {bundleName}"); AssetBundleInfo bundleInfo = new AssetBundleInfo(bundleName, string.Empty); return(bundleInfo); } }
/// <summary> /// 异步初始化 /// </summary> public IEnumerator InitializeAync(PatchManagerImpl patcher) { // 处理沙盒被污染 ProcessSandboxDirty(); // 分析APP内的补丁清单 { string filePath = AssetPathHelper.MakeStreamingLoadPath(PatchDefine.PatchManifestBytesFileName); string url = AssetPathHelper.ConvertToWWWPath(filePath); WebDataRequest downloader = new WebDataRequest(url); yield return(downloader.DownLoad()); if (downloader.States == EWebRequestStates.Success) { MotionLog.Log("Parse app patch manifest."); patcher.ParseAppPatchManifest(downloader.GetData()); downloader.Dispose(); } else { throw new System.Exception($"Fatal error : Failed download file : {url}"); } } // 分析沙盒内的补丁清单 if (PatchHelper.CheckSandboxPatchManifestFileExist()) { string filePath = AssetPathHelper.MakePersistentLoadPath(PatchDefine.PatchManifestBytesFileName); byte[] fileData = File.ReadAllBytes(filePath); MotionLog.Log($"Parse sandbox patch file."); patcher.ParseSandboxPatchManifest(fileData); } else { patcher.ParseSandboxPatchManifest(patcher.AppPatchManifest); } }
/// <summary> /// 异步初始化 /// </summary> public IEnumerator InitializeAsync() { MotionLog.Log($"Beginning to initialize patch manager."); // 加载缓存 _cache = PatchCache.LoadCache(); // 检测沙盒被污染 // 注意:在覆盖安装的时候,会保留沙盒目录里的文件,所以需要强制清空 { // 如果是首次打开,记录APP版本号 if (PatchHelper.CheckSandboxCacheFileExist() == false) { _cache.CacheAppVersion = Application.version; _cache.SaveCache(); } else { // 每次启动时比对APP版本号是否一致 if (_cache.CacheAppVersion != Application.version) { MotionLog.Warning($"Cache is dirty ! Cache version is {_cache.CacheAppVersion}, APP version is {Application.version}"); ClearCache(); // 重新写入最新的APP版本号 _cache.CacheAppVersion = Application.version; _cache.SaveCache(); } } } // 加载APP内的补丁清单 MotionLog.Log($"Load app patch manifest."); { string filePath = AssetPathHelper.MakeStreamingLoadPath(PatchDefine.PatchManifestFileName); string url = AssetPathHelper.ConvertToWWWPath(filePath); WebGetRequest downloader = new WebGetRequest(url); downloader.DownLoad(); yield return(downloader); if (downloader.HasError()) { downloader.ReportError(); downloader.Dispose(); throw new System.Exception($"Fatal error : Failed download file : {url}"); } // 解析补丁清单 string jsonData = downloader.GetText(); _appPatchManifest = PatchManifest.Deserialize(jsonData); downloader.Dispose(); } // 加载沙盒内的补丁清单 MotionLog.Log($"Load sandbox patch manifest."); if (PatchHelper.CheckSandboxPatchManifestFileExist()) { string filePath = AssetPathHelper.MakePersistentLoadPath(PatchDefine.PatchManifestFileName); string jsonData = File.ReadAllText(filePath); _localPatchManifest = PatchManifest.Deserialize(jsonData); } else { _localPatchManifest = _appPatchManifest; } }
private IEnumerator Download() { // 注意:开发者需要在下载前检测磁盘空间不足 // 计算下载文件的总大小 int totalDownloadCount = _patcher.DownloadList.Count; long totalDownloadSizeBytes = 0; foreach (var element in _patcher.DownloadList) { totalDownloadSizeBytes += element.SizeBytes; } // 开始下载列表里的所有资源 PatchHelper.Log(ELogLevel.Log, $"Begine download web files : {_patcher.DownloadList.Count}"); long currentDownloadSizeBytes = 0; int currentDownloadCount = 0; foreach (var element in _patcher.DownloadList) { // 注意:资源版本号只用于确定下载路径 string url = _patcher.GetWebDownloadURL(element.Version.ToString(), element.Name); string savePath = AssetPathHelper.MakePersistentLoadPath(element.Name); element.SavePath = savePath; FileUtility.CreateFileDirectory(savePath); // 创建下载器 WebFileRequest download = new WebFileRequest(url, savePath); yield return(download.DownLoad()); //文件依次加载(在一个文件加载完毕后加载下一个) PatchHelper.Log(ELogLevel.Log, $"Web file is download : {savePath}"); // 检测是否下载失败 if (download.States != EWebRequestStates.Success) { PatchEventDispatcher.SendWebFileDownloadFailedMsg(url, element.Name); yield break; } // 立即释放加载器 download.Dispose(); currentDownloadCount++; currentDownloadSizeBytes += element.SizeBytes; PatchEventDispatcher.SendDownloadFilesProgressMsg(totalDownloadCount, currentDownloadCount, totalDownloadSizeBytes, currentDownloadSizeBytes); } // 验证下载文件的大小 if (_patcher.CheckLevel == ECheckLevel.CheckSize) { foreach (var element in _patcher.DownloadList) { long fileSize = FileUtility.GetFileSize(element.SavePath); if (fileSize != element.SizeBytes) { PatchHelper.Log(ELogLevel.Error, $"Web file size check failed : {element.Name}"); PatchEventDispatcher.SendWebFileCheckFailedMsg(element.Name); yield break; } } } // 验证下载文件的MD5 if (_patcher.CheckLevel == ECheckLevel.CheckMD5) { foreach (var element in _patcher.DownloadList) { string md5 = HashUtility.FileMD5(element.SavePath); if (md5 != element.MD5) { PatchHelper.Log(ELogLevel.Error, $"Web file md5 check failed : {element.Name}"); PatchEventDispatcher.SendWebFileCheckFailedMsg(element.Name); yield break; } } } // 最后清空下载列表 _patcher.DownloadList.Clear(); _patcher.SwitchNext(); }
private IEnumerator Download() { // 如果忽略资源版本,那么每次启动都会下载补丁清单 bool ignoreResourceVersion = _patcher.IgnoreResourceVersion; // 新安装的用户首次启动游戏(包括覆盖安装的用户) // 注意:请求的补丁清单会在下载流程结束的时候,自动保存在沙盒里。 bool firstStartGame = PatchHelper.CheckSandboxPatchManifestFileExist() == false; // 检测资源版本是否变化 int newResourceVersion = _patcher.RequestedResourceVersion; int oldResourceVersion = _patcher.LocalResourceVersion; if (ignoreResourceVersion == false && firstStartGame == false && newResourceVersion == oldResourceVersion) { MotionLog.Log($"Resource version is not change."); _patcher.Switch(EPatchStates.PatchDone); } else { // 从远端请求补丁清单 _requestCount++; string url = GetRequestURL(ignoreResourceVersion, newResourceVersion, PatchDefine.PatchManifestFileName); WebGetRequest download = new WebGetRequest(url); download.SendRequest(); yield return(download); // Check fatal if (download.HasError()) { download.ReportError(); download.Dispose(); PatchEventDispatcher.SendPatchManifestRequestFailedMsg(); yield break; } // 解析补丁清单 _patcher.ParseRemotePatchManifest(download.GetText()); download.Dispose(); // 如果发现了新的安装包 if (_patcher.FoundNewApp) { string requestedGameVersion = _patcher.RequestedGameVersion.ToString(); MotionLog.Log($"Found new APP can be install : {requestedGameVersion}"); PatchEventDispatcher.SendFoundNewAppMsg(_patcher.ForceInstall, _patcher.AppURL, requestedGameVersion); } else { if (firstStartGame) { MotionLog.Log("First start game."); } if (newResourceVersion != oldResourceVersion) { MotionLog.Log($"Resource version is change : {oldResourceVersion} -> {newResourceVersion}"); } _patcher.SwitchNext(); } } }