public override IEnumerator DownLoad() { // Check fatal if (States != EWebRequestStates.None) { throw new Exception($"{nameof(WebFileRequest)} is downloading yet : {URL}"); } States = EWebRequestStates.Loading; // 下载文件 CacheRequest = new UnityWebRequest(URL, UnityWebRequest.kHttpVerbGET); DownloadHandlerFile handler = new DownloadHandlerFile(SavePath); handler.removeFileOnAbort = true; CacheRequest.downloadHandler = handler; CacheRequest.disposeDownloadHandlerOnDispose = true; CacheRequest.timeout = Timeout; yield return(CacheRequest.SendWebRequest()); // Check error if (CacheRequest.isNetworkError || CacheRequest.isHttpError) { MotionLog.Log(ELogLevel.Warning, $"Failed to download web file : {URL} Error : {CacheRequest.error}"); States = EWebRequestStates.Fail; } else { States = EWebRequestStates.Success; } }
private void GetDownloadList() { // 获取游戏启动时的下载列表 var downloadList = _patcher.GetAutoPatchDownloadList(); // 如果下载列表为空 if (downloadList.Count == 0) { MotionLog.Log("Not found update web files."); _patcher.Switch(EPatchStates.DownloadOver.ToString()); } else { MotionLog.Log($"Found update web files : {downloadList.Count}"); // 创建补丁下载器 _patcher.CreateInternalDownloader(downloadList); // 发现新更新文件后,挂起流程系统 // 注意:开发者需要在下载前检测磁盘空间不足 int totalDownloadCount = _patcher.InternalDownloader.TotalDownloadCount; long totalDownloadBytes = _patcher.InternalDownloader.TotalDownloadBytes; PatchEventDispatcher.SendFoundUpdateFilesMsg(totalDownloadCount, totalDownloadBytes); } }
private void Handle_Completed(AssetOperationHandle obj) { try { TextAsset txt = _handle.AssetObject as TextAsset; if (txt != null) { // 解析数据 ParseDataInternal(txt.bytes); } } catch (Exception ex) { MotionLog.Log(ELogLevel.Error, $"Failed to parse config {Location}. Error : {ex.ToString()}"); } // 注意:为了节省内存这里立即释放了资源 if (_assetRef != null) { _assetRef.Release(); _assetRef = null; } IsPrepare = true; _userCallback?.Invoke(this); }
/// <summary> /// 处理沙盒被污染 /// 注意:在覆盖安装的时候,会保留沙盒目录里的文件,所以需要强制清空。 /// </summary> private void ProcessSandboxDirty() { string appVersion = PatchManager.Instance.GetAPPVersion(); string filePath = PatchHelper.GetSandboxStaticFilePath(); // 如果是首次打开,记录APP版本信息 if (PatchHelper.CheckSandboxStaticFileExist() == false) { MotionLog.Log($"Create sandbox static file : {filePath}"); FileUtility.CreateFile(filePath, appVersion); return; } // 每次启动时比对APP版本号是否一致 string recordVersion = FileUtility.ReadFile(filePath); // 如果记录的版本号不一致 if (recordVersion != appVersion) { MotionLog.Warning($"Sandbox is dirty, Record version is {recordVersion}, APP version is {appVersion}"); MotionLog.Warning("Clear all sandbox files."); PatchHelper.ClearSandbox(); // 重新写入最新的APP版本信息 MotionLog.Log($"Recreate sandbox static file : {filePath}"); FileUtility.CreateFile(filePath, appVersion); } }
/// <summary> /// 处理连接请求 /// </summary> private void ProcessConnected(object obj) { SocketAsyncEventArgs e = obj as SocketAsyncEventArgs; UserToken token = (UserToken)e.UserToken; if (e.SocketError == SocketError.Success) { if (_channel != null) { throw new Exception("TcpClient channel is created."); } // 创建频道 _channel = new TcpChannel(); _channel.InitChannel(e.ConnectSocket, _packageCoderType, _packageMaxSize); } else { MotionLog.Log(ELogLevel.Error, $"ProcessConnected error : {e.SocketError}"); } // 回调函数 if (token.Callback != null) { token.Callback.Invoke(e.SocketError); } }
public IEnumerator Download() { // 请求游戏版本 string webURL = _patcher.GetWebServerURL(); string postContent = _patcher.GetWebPostContent(); MotionLog.Log($"Beginning to request from web : {webURL}"); MotionLog.Log($"Web post content : {postContent}"); WebPostRequest download = new WebPostRequest(webURL); download.SendRequest(postContent); yield return(download); // Check fatal if (download.HasError()) { download.ReportError(); download.Dispose(); PatchEventDispatcher.SendGameVersionRequestFailedMsg(); yield break; } string responseContent = download.GetResponse(); MotionLog.Log($"Succeed get response from web : {responseContent}"); download.Dispose(); _patcher.ParseResponseContent(responseContent); _patcher.SwitchNext(); }
/// <summary> /// 转换节点 /// </summary> public void Transition(string nodeName) { if (string.IsNullOrEmpty(nodeName)) { throw new ArgumentNullException(); } IFsmNode node = GetNode(nodeName); if (node == null) { MotionLog.Error($"Can not found node {nodeName}"); return; } // 检测转换关系 if (Graph != null) { if (Graph.CanTransition(_curNode.Name, node.Name) == false) { MotionLog.Error($"Can not transition {_curNode} to {node}"); return; } } MotionLog.Log($"Transition {_curNode.Name} to {node.Name}"); _preNode = _curNode; _curNode.OnExit(); _curNode = node; _curNode.OnEnter(); }
/// <summary> /// 捕获异常错误 /// </summary> public void HandleError(bool isDispose, string error) { MotionLog.Log(ELogLevel.Error, error); if (isDispose) { Dispose(); } }
/// <summary> /// 保存缓存文件 /// </summary> public void SaveCache() { MotionLog.Log("Save cache to disk."); string filePath = PatchHelper.GetSandboxCacheFilePath(); string jsonData = JsonUtility.ToJson(this); FileUtility.CreateFile(filePath, jsonData); }
public void SaveRemotePatchManifest() { // 注意:这里会覆盖掉沙盒内的补丁清单文件 MotionLog.Log("Save remote patch manifest."); string savePath = AssetPathHelper.MakePersistentLoadPath(PatchDefine.PatchManifestFileName); PatchManifest.Serialize(savePath, _localPatchManifest); }
/// <summary> /// 创建指定资源的游戏对象池 /// </summary> public void CreatePool(string location, int capacity = 0) { if (_collectors.ContainsKey(location)) { MotionLog.Log(ELogLevel.Warning, $"Asset is already existed : {location}"); return; } CreatePoolInternal(location, capacity); }
/// <summary> /// 开始下载 /// </summary> public void Download() { if (DownloadStates != EDownloaderStates.None) { throw new System.Exception($"{nameof(PatchDownloader)} is already running."); } MotionLog.Log($"Begine to download : {TotalDownloadCount} files and {TotalDownloadBytes} bytes"); DownloadStates = EDownloaderStates.Loading; }
/// <summary> /// 获取配表 /// </summary> /// <param name="configName">配表文件名称</param> public AssetConfig GetConfig(string configName) { if (_configs.ContainsKey(configName)) { return(_configs[configName]); } MotionLog.Log(ELogLevel.Error, $"Not found config {configName}"); return(null); }
/// <summary> /// 注册变体规则 /// </summary> /// <param name="variantGroup">变体组</param> /// <param name="targetVariant">目标变体</param> public void RegisterVariantRule(List <string> variantGroup, string targetVariant) { if (variantGroup == null || variantGroup.Count == 0) { throw new Exception("VariantGroup is null or empty."); } if (string.IsNullOrEmpty(targetVariant)) { throw new Exception("TargetVariant is invalid."); } // 需要包含点前缀 for (int i = 0; i < variantGroup.Count; i++) { string variant = variantGroup[i]; if (variant.Contains(".") == false) { variantGroup[i] = $".{variant}"; } } if (targetVariant.Contains(".") == false) { targetVariant = $".{targetVariant}"; } // 目标变体需要在变体组列表里 if (variantGroup.Contains(targetVariant) == false) { throw new Exception($"Variant group not contains target variant : {targetVariant} "); } // 转换为小写形式 targetVariant = targetVariant.ToLower(); for (int i = 0; i < variantGroup.Count; i++) { variantGroup[i] = variantGroup[i].ToLower(); } foreach (var variant in variantGroup) { if (variant == targetVariant) { continue; } if (_variantRuleCollection.ContainsKey(variant) == false) { _variantRuleCollection.Add(variant, targetVariant); } else { MotionLog.Log(ELogLevel.Warning, $"Variant key {variant} is already existed."); } } }
/// <summary> /// 运行流程系统 /// </summary> public void Run() { if (_nodeNames.Count > 0) { _fsm.Run(_nodeNames[0]); } else { MotionLog.Log(ELogLevel.Warning, "Procedure system dont has any node."); } }
public void CacheDownloadPatchFiles(List <PatchBundle> downloadList) { List <string> hashList = new List <string>(downloadList.Count); foreach (var patchBundle in downloadList) { MotionLog.Log($"Cache download web file : {patchBundle.BundleName} Version : {patchBundle.Version} Hash : {patchBundle.Hash}"); hashList.Add(patchBundle.Hash); } _cache.CacheDownloadPatchFiles(hashList); }
public void CacheDownloadPatchFiles(List <PatchElement> downloadList) { List <string> hashList = new List <string>(downloadList.Count); foreach (var element in downloadList) { MotionLog.Log($"Cache download file : {element.BundleName} : {element.Version}"); hashList.Add(element.MD5); } _cache.CacheDownloadPatchFiles(hashList); }
// 缓存系统相关 public void CacheDownloadPatchFile(string bundleName) { if (_localPatchManifest.Elements.TryGetValue(bundleName, out PatchElement element)) { MotionLog.Log($"Cache download file : {element.BundleName} : {element.Version}"); _cache.CacheDownloadPatchFile(element.MD5); } else { MotionLog.Warning($"Not found cache content file in local patch manifest : {bundleName}"); } }
/// <summary> /// 获取数据,如果不存在报警告 /// </summary> public ConfigTable GetTable(int key) { if (_tables.ContainsKey(key)) { return(_tables[key]); } else { MotionLog.Log(ELogLevel.Warning, $"Faild to get tab. File is {Location}, key is {key}"); return(null); } }
/// <summary> /// 开启更新 /// </summary> public void Download() { MotionLog.Log("Begin to run patch procedure."); // 注意:按照先后顺序添加流程节点 _procedure.AddNode(new FsmRequestGameVersion(this)); _procedure.AddNode(new FsmGetWebPatchManifest(this)); _procedure.AddNode(new FsmGetDonwloadList(this)); _procedure.AddNode(new FsmDownloadWebFiles(this)); _procedure.AddNode(new FsmDownloadOver(this)); _procedure.Run(); }
// 缓存系统相关 public void CacheDownloadPatchFile(string bundleName) { if (_localPatchManifest.Bundles.TryGetValue(bundleName, out PatchBundle patchBundle)) { MotionLog.Log($"Cache download web file : {patchBundle.BundleName} Version : {patchBundle.Version} Hash : {patchBundle.Hash}"); _cache.CacheDownloadPatchFile(patchBundle.Hash); } else { MotionLog.Warning($"Not found bundle in local patch manifest : {bundleName}"); } }
/// <summary> /// 发送网络消息 /// </summary> public void SendMessage(INetworkPackage package) { if (States != ENetworkStates.Connected) { MotionLog.Log(ELogLevel.Warning, "Network is not connected."); return; } if (_client != null) { _client.SendPackage(package); } }
/// <summary> /// 切换至上个流程节点 /// </summary> public void SwitchLast() { int index = _nodeNames.IndexOf(_fsm.CurrentNodeName); if (index <= 0) { MotionLog.Log(ELogLevel.Warning, $"Current node {_fsm.CurrentNodeName} is begin node."); } else { Switch(_nodeNames[index - 1]); } }
/// <summary> /// 切换至下个流程节点 /// </summary> public void SwitchNext() { int index = _nodeNames.IndexOf(_fsm.CurrentNodeName); if (index >= _nodeNames.Count - 1) { MotionLog.Log(ELogLevel.Warning, $"Current node {_fsm.CurrentNodeName} is end node."); } else { Switch(_nodeNames[index + 1]); } }
/// <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)); }
/// <summary> /// 获取配表 /// </summary> public T GetConfig <T>() where T : AssetConfig { System.Type type = typeof(T); foreach (var pair in _configs) { if (pair.Value.GetType() == type) { return(pair.Value as T); } } MotionLog.Log(ELogLevel.Error, $"Not found config {type}"); return(null); }
public IEnumerator Download() { // 获取最新的游戏版本号 { string url = _patcher.GetWebServerIP(); string post = _patcher.GetWebPostData(); MotionLog.Log($"Beginning to request from web : {url} {post}"); WebPostRequest download = new WebPostRequest(url, post); download.DownLoad(); yield return(download); //Check fatal if (download.HasError()) { download.ReportError(); download.Dispose(); PatchEventDispatcher.SendGameVersionRequestFailedMsg(); yield break; } string response = download.GetResponse(); MotionLog.Log($"Succeed get response from web : {url} {response}"); _patcher.ParseWebResponseData(response); download.Dispose(); } // 检测强更安装包 if (_patcher.ForceInstall) { string requestedGameVersion = _patcher.RequestedGameVersion.ToString(); MotionLog.Log($"Found new APP can be install : {requestedGameVersion}"); PatchEventDispatcher.SendFoundForceInstallAPPMsg(requestedGameVersion, _patcher.AppURL); yield break; } // 检测资源版本是否变化 int newResourceVersion = _patcher.RequestedResourceVersion; int oldResourceVersion = _patcher.LocalResourceVersion; if (newResourceVersion == oldResourceVersion) { MotionLog.Log($"Resource version is not change."); _patcher.Switch(EPatchStates.DownloadOver.ToString()); } else { MotionLog.Log($"Resource version is change : {oldResourceVersion} -> {newResourceVersion}"); _patcher.SwitchNext(); } }
private void OnConnectServer(SocketError error) { MotionLog.Log($"Server connect result : {error}"); if (error == SocketError.Success) { States = ENetworkStates.Connected; NetworkEventDispatcher.SendConnectSuccessMsg(); } else { States = ENetworkStates.Disconnect; NetworkEventDispatcher.SendConnectFailMsg(error.ToString()); } }
public void UnLoad() { if (_handle != null) { MotionLog.Log($"Begin to unload scene : {Location}"); _finishCallback = null; _progressCallback = null; _lastProgressValue = 0; // 异步卸载场景 _handle.UnloadAsync(); _handle = null; } }
/// <summary> /// 启动状态机 /// </summary> /// <param name="entryNode">入口节点</param> public void Run(string entryNode) { _curNode = GetNode(entryNode); _preNode = GetNode(entryNode); if (_curNode != null) { _curNode.OnEnter(); } else { MotionLog.Log(ELogLevel.Error, $"Not found entry node : {entryNode}"); } }