using System; using System.Collections.Generic; using System.IO; using System.Collections; using Thousandto.Update.Singleton; using Thousandto.Update.Download; using Thousandto.Update.Flow; using Thousandto.Update.Data; using Thousandto.Update.Log; using Thousandto.Update.Delegate; using DownloadSpeeder = UnityEngine.Gonbest.MagicCube.DownloadSpeeder; namespace Thousandto.Update.Manager { /// /// 管理后台更新 /// public partial class UpdateManager : Singleton { //总的静默更新资源大小 private int _totalBaseResSize = 0; #region //Instance private Flow8ExCheckResource _instance; private Flow8ExCheckResource InstanceFlow8Ex { get { if (_instance == null) _instance = FlowInstance(); return _instance; } } #endregion //场景资源列表 private Dictionary> _sceneResList = new Dictionary>(); //存储下载完成的文件 private Dictionary _downloadedFileDic = new Dictionary(); private void AddDataList(IEnumerable dataList, DataLevel level, bool append = false) { if (dataList != null && !append) { BackDownload.ClearData(level); if (_sceneResList.ContainsKey(level) && _sceneResList[level] != null) { _sceneResList[level].Clear(); } } Flow8ExCheckResource resource = InstanceFlow8Ex; string fixPath = ""; IEnumerator enumerator = dataList.GetEnumerator(); while (enumerator.MoveNext()) { //不存在的文件才加入到下载队列 if (!Exist(enumerator.Current as string, out fixPath)) { lock (BackDownload.GetLocker()) { MapFileData mapFileData = resource.GetMapFileDataByPath(fixPath); if (((mapFileData == null) || mapFileData.Downloading) || mapFileData.Downloaded) { //UpdateLog.WARN_LOG("no map data: " + fixPath); } else { mapFileData.FullPath = fixPath; if (mapFileData.PriorityLevel > (int)level) { mapFileData.PriorityLevel = (int)level; } BackDownload.AddDataToPool(mapFileData, level); //添加到当前场景资源列表,用于统计大小,显示进度 AddToCurSceneResList(level, mapFileData); } } } } } /// /// 添加到当前场景资源 /// /// /// private void AddToCurSceneResList(DataLevel level, MapFileData data) { if (level == DataLevel.CurScene) { if (!_sceneResList.ContainsKey(level)) { var dataList = new List(); dataList.Add(data); _sceneResList.Add(level, dataList); } else { _sceneResList[level].Add(data); } } } /// /// 游戏内调用,用于判断某场景是否存在 /// 如果不存在,则需要提示4G玩家等待 /// /// /// public bool IsExist(string absolutPath) { string fixPath = absolutPath; MapFileData data = null; return IsExistOrDownloaded(absolutPath, out data, out fixPath); } /// /// 判断文件路径是否有效,本地不存在文件,map中又没有这个文件,则判定为无效 /// /// /// public bool IsFileValid(string absPath,out bool isExist) { string fixPath = absPath; MapFileData data = null; isExist = IsExistOrDownloaded(absPath, out data, out fixPath); return (isExist || (data != null)); } /// /// 判断是否正在下载中,如果是,则不做提示 /// /// /// public bool IsExist(string absolutPath, out bool downloading) { downloading = false; string fixPath = absolutPath; MapFileData data = null; bool ret = IsExistOrDownloaded(absolutPath, out data, out fixPath); if (data != null) { downloading = data.Downloading; } return ret; } /// /// 设置后台下载速度 /// /// kb/s public void SetDownloadSpeed(int kbPerSecond) { BackDownload.SetDownloadSpeed(kbPerSecond); } /// /// 下载资源 /// /// /// /// /// public bool DownloadResource(string absolutPath, UpdateAction callback, object obj) { string fixPath = absolutPath; MapFileData data = null; if (!IsExistOrDownloaded(absolutPath, out data, out fixPath)) { if (data != null) { lock (BackDownload.GetLocker()) { //暂停中,则不接受请求,原样返回 if (IsPaused()) { UpdateLog.WARN_LOG("当前是暂停状态,直接返回请求:" + absolutPath); data.DownloadCallBack = null; data.ArgObj = null; callback(fixPath, CodeDefine.RET_BACKDOWNLOAD_SKIPBYPAUSE, obj); return true; } else { data.DownloadCallBack = callback; data.ArgObj = obj; data.PriorityLevel = (int)DataLevel.High; } } if (!data.Downloading) { //UpdateLog.DEBUG_LOG("start load file: " + fixPath); BackDownload.AddDataToPool(data, DataLevel.High); } else UpdateLog.WARN_LOG("resource is downloading: " + fixPath); } else { //UpdateLog.WARN_LOG("no map data found: " + absolutPath); callback(absolutPath, CodeDefine.RET_BACKDOWNLOAD_INVALIDFILE, obj); } return true; } else { callback(fixPath, CodeDefine.RET_BACKDOWNLOAD_ALREADYEXIST, obj); } return false; } /// /// 获取当前场景下载信息 /// /// /// public void GetCurSceneTotalResSize(out long total, out long downloaded) { downloaded = 0; total = 0; try { if (_sceneResList.ContainsKey(DataLevel.CurScene)) { var resList = _sceneResList[DataLevel.CurScene]; for (int i = 0; i < resList.Count; ++i) { downloaded += BackDownload.GetMapDataDownloadedSize(resList[i]); total += resList[i].FileSize; } } } catch (System.Exception ex) { UpdateLog.ERROR_LOG(ex.Message + "\n" + ex.StackTrace); } } /// /// 暂停所有 /// public void PauseAll() { BackDownload.PauseAll(); } /// /// 恢复所有 /// public void ResumeAll() { BackDownload.ResumeAll(); } /// /// 暂停后台下载 /// public void PauseBaseDownload() { BackDownload.PauseLevel(DataLevel.Low); } /// /// 恢复后台下载,与pause成对 /// public void ResumeBaseDownload() { BackDownload.ResumeLevel(DataLevel.Low); } /// /// 暂停当前场景下载 /// public void PauseCurSceneDownload() { BackDownload.PauseLevel(DataLevel.CurScene); } /// /// 恢复当前场景下载 /// public void ResumeCurSceneDownload() { BackDownload.ResumeLevel(DataLevel.CurScene); } public bool IsPaused() { return BackDownload.IsPaused(); } /// /// 是否暂停静默更新 /// /// public bool IsBaseResPaused() { return BackDownload.IsBaseResPaused(); } /// /// 是否暂停当前场景更新 /// /// public bool IsCurScenePaused() { return BackDownload.IsCurScenePaused(); } /// /// 当前场景资源是否下载完了 /// 需要判断队列中是否存在和是否正在下载 /// /// public bool IsCurSceneDownloadFinish() { if(_sceneResList.ContainsKey(DataLevel.CurScene)) { var curSceneResList = _sceneResList[DataLevel.CurScene]; for (int i = 0; i < curSceneResList.Count; ++i) { if (!File.Exists(curSceneResList[i].FullPath)) return false; } } return true; } /// /// 是否静默更新下载完了 /// /// public bool IsBaseResDownloadFinish() { return BackDownload.GetDataCount(DataLevel.Low) == 0; } /// /// 本身存在或者下载完成的文件 /// /// /// /// /// internal bool IsExistOrDownloaded(string absolutPath, out MapFileData data, out string fixPath) { bool ret = false; fixPath = absolutPath; data = null; //1.检查是否在包体内 //1.1: 如果不在存储路径,并且包体内存在,那么就返回为true.这个判断一般对IOS有效,对于Android是无效的. //1.2: 判断FileList中是否存在. //2.检查是否下载 //2.1.如果已经下载完毕,那么就直接返回true //2.2.判断是否在MapFile中是否存在. //2.2.1.如果当前文件没有下载,并且文件存在,放到downloaded缓存中,那么就直接返回 //2.2.2.如果当前文件已经下载完成,那么直接使用. //2.2.3.如果当前文件已经正在下载或者没有下载,那么就把当前文件放到最优先下载的队列中. //如果是包内路径 if (!string.IsNullOrEmpty(_appPath) && (absolutPath.IndexOf(_appPath) >= 0)) { //拼接存储路径 string path = absolutPath.Replace(_appPath, _storePath); //包内存在文件,存储路径不存在文件,直接返回 if (!File.Exists(path) && File.Exists(absolutPath)) { ret = true; return ret; } //将路径转换成存储路径 fixPath = path; absolutPath = fixPath; } else { string relativePath = absolutPath.Replace(_storePath, ""); if (relativePath.StartsWith("/")) { relativePath = relativePath.Substring(1); } string md5 = null; int size = 0; if(TryGetInAppData(relativePath, out md5, out size)) { ret = true; return ret; } } { //已经下载好了,直接返回 if (_downloadedFileDic.ContainsKey(absolutPath)) { ret = true; } else { //获取对应的MapData数据 MapFileData mapFileDataByPath = InstanceFlow8Ex.GetMapFileDataByPath(absolutPath); if (mapFileDataByPath != null) { bool skipDownload = false; //lock (BackDownload.GetLocker()) { //没有在下载中,并且存在这个文件,直接返回 if (!mapFileDataByPath.Downloading && File.Exists(absolutPath)) { _downloadedFileDic.Add(absolutPath, 0); skipDownload = true; } //下载完成状态,直接返回 else if (mapFileDataByPath.Downloaded) { _downloadedFileDic.Add(absolutPath, 0); skipDownload = true; } else { //没下载或下载中状态,添加到高优先级的下载队列 data = mapFileDataByPath; } } ret = skipDownload; } else if (File.Exists(absolutPath)) { //没有找到MapData数据,但是文件存在,依然返回true ret = true; } } } return ret; } /// /// 后台更新当前场景资源 /// /// /// internal void BackDownloadCurSceneData(string[] normalList, bool append = false) { UpdateLog.WARN_LOG("Add cur scene resources"); AddDataList(normalList, DataLevel.CurScene, append); } /// /// 后台更新下一场景资源 /// /// /// internal void BackDownloadNextSceneData(string[] preLoadList, bool append = false) { AddDataList(preLoadList, DataLevel.NextScene, append); } /// /// 下载场景资源 /// /// 要下载的场景ID /// 是否当前场景 public void BackDownloadSceneData(int mapID, bool current = false, bool append = false) { string str = string.Format("{1}/{0}.txt", mapID, _sceneConfigPath); string path = _storePath + "/" + str; if (!File.Exists(path)) path = _appPath + "/" + str; if (File.Exists(path)) { UpdateLog.WARN_LOG("download scene resource: " + str); string[] normalList = File.ReadAllLines(path); if (current) { BackDownloadCurSceneData(normalList, append); } else { BackDownloadNextSceneData(normalList, append); } } else { UpdateLog.WARN_LOG("找不到文件: " + path); } } public void BackDownloadSceneData(string[] preLoadList, bool append = false) { AddDataList(preLoadList, DataLevel.NextScene, append); } /// /// 静默后台更新所有资源 /// public void BackDownloadTotalData() { DownloadSpeeder.Reset(); _totalBaseResSize = 0; Flow8ExCheckResource resource = InstanceFlow8Ex; if (resource.BackDownloadList != null) { for (int i = 0; i < resource.BackDownloadList.Count; i++) { BackDownload.AddDataToPool(resource.BackDownloadList[i], DataLevel.Low); _totalBaseResSize += resource.BackDownloadList[i].FileSize; } } } /// /// 总的后台下载资源大小 /// /// public int GetTotalBaseResSize() { return _totalBaseResSize; } /// /// 总的已下载大小 /// /// public int GetTotalDownloadedSize() { return DownloadSpeeder.CurTotalSize; //return BackDownload.TotalDownloadedSize; } /// /// 获取下载速度 /// /// public int GetDownloadSpeed() { return DownloadSpeeder.CalcSpeed(); } /// /// 初始化后台更新 /// internal void InitBackDownload(int halfCpuCoreCount = 4) { //初始化后台更新模块 Thousandto.Update.Download.BackDownload.InitPool(halfCpuCoreCount, convertMyActionCall(delegate(string arg1, int arg2, object arg3) { MapFileData data = arg3 as MapFileData; if (arg2 < CodeDefine.RET_BACKDOWNLOAD_SUCCESS) { UpdateLog.ERROR_LOG("下载失败: " + arg1); } var func = data.DownloadCallBack; //需要设置为null,不然重复下载的文件会出问题 data.DownloadCallBack = null; if (func != null) { func(arg1, arg2, data.ArgObj); } data.Downloading = false; data.Downloaded = arg2 >= CodeDefine.RET_BACKDOWNLOAD_SUCCESS; })); } private bool Exist(string path, out string fixPath) { if (path.IndexOf(_storePath) == 0) { fixPath = path; } else { fixPath = Path.Combine(_storePath, path).Replace(@"\", "/"); } return File.Exists(fixPath); } } }