Files
Main/Assets/Plugins/References/FuncellUpdate/UpdateModel/UpdateManagerBackDownload.cs

596 lines
20 KiB
C#
Raw Normal View History

2025-01-25 04:38:09 +08:00
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
{
/// <summary>
/// 管理后台更新
/// </summary>
public partial class UpdateManager : Singleton<UpdateManager>
{
//总的静默更新资源大小
private int _totalBaseResSize = 0;
#region //Instance
private Flow8ExCheckResource _instance;
private Flow8ExCheckResource InstanceFlow8Ex
{
get
{
if (_instance == null) _instance = FlowInstance<Flow8ExCheckResource>();
return _instance;
}
}
#endregion
//场景资源列表
private Dictionary<DataLevel, List<MapFileData>> _sceneResList = new Dictionary<DataLevel, List<MapFileData>>();
//存储下载完成的文件
private Dictionary<string, int> _downloadedFileDic = new Dictionary<string, int>();
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);
}
}
}
}
}
/// <summary>
/// 添加到当前场景资源
/// </summary>
/// <param name="level"></param>
/// <param name="data"></param>
private void AddToCurSceneResList(DataLevel level, MapFileData data)
{
if (level == DataLevel.CurScene)
{
if (!_sceneResList.ContainsKey(level))
{
var dataList = new List<MapFileData>();
dataList.Add(data);
_sceneResList.Add(level, dataList);
}
else
{
_sceneResList[level].Add(data);
}
}
}
/// <summary>
/// 游戏内调用,用于判断某场景是否存在
/// 如果不存在则需要提示4G玩家等待
/// </summary>
/// <param name="absolutPath"></param>
/// <returns></returns>
public bool IsExist(string absolutPath)
{
string fixPath = absolutPath;
MapFileData data = null;
return IsExistOrDownloaded(absolutPath, out data, out fixPath);
}
/// <summary>
/// 判断文件路径是否有效本地不存在文件map中又没有这个文件则判定为无效
/// </summary>
/// <param name="absPath"></param>
/// <returns></returns>
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));
}
/// <summary>
/// 判断是否正在下载中,如果是,则不做提示
/// </summary>
/// <param name="absolutPath"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 设置后台下载速度
/// </summary>
/// <param name="kbPerSecond">kb/s</param>
public void SetDownloadSpeed(int kbPerSecond)
{
BackDownload.SetDownloadSpeed(kbPerSecond);
}
/// <summary>
/// 下载资源
/// </summary>
/// <param name="absolutPath"></param>
/// <param name="callback"></param>
/// <param name="obj"></param>
/// <returns></returns>
public bool DownloadResource(string absolutPath, UpdateAction<string, int, object> 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;
}
/// <summary>
/// 获取当前场景下载信息
/// </summary>
/// <param name="total"></param>
/// <param name="downloaded"></param>
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);
}
}
/// <summary>
/// 暂停所有
/// </summary>
public void PauseAll()
{
BackDownload.PauseAll();
}
/// <summary>
/// 恢复所有
/// </summary>
public void ResumeAll()
{
BackDownload.ResumeAll();
}
/// <summary>
/// 暂停后台下载
/// </summary>
public void PauseBaseDownload()
{
BackDownload.PauseLevel(DataLevel.Low);
}
/// <summary>
/// 恢复后台下载与pause成对
/// </summary>
public void ResumeBaseDownload()
{
BackDownload.ResumeLevel(DataLevel.Low);
}
/// <summary>
/// 暂停当前场景下载
/// </summary>
public void PauseCurSceneDownload()
{
BackDownload.PauseLevel(DataLevel.CurScene);
}
/// <summary>
/// 恢复当前场景下载
/// </summary>
public void ResumeCurSceneDownload()
{
BackDownload.ResumeLevel(DataLevel.CurScene);
}
public bool IsPaused()
{
return BackDownload.IsPaused();
}
/// <summary>
/// 是否暂停静默更新
/// </summary>
/// <returns></returns>
public bool IsBaseResPaused()
{
return BackDownload.IsBaseResPaused();
}
/// <summary>
/// 是否暂停当前场景更新
/// </summary>
/// <returns></returns>
public bool IsCurScenePaused()
{
return BackDownload.IsCurScenePaused();
}
/// <summary>
/// 当前场景资源是否下载完了
/// 需要判断队列中是否存在和是否正在下载
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 是否静默更新下载完了
/// </summary>
/// <returns></returns>
public bool IsBaseResDownloadFinish()
{
return BackDownload.GetDataCount(DataLevel.Low) == 0;
}
/// <summary>
/// 本身存在或者下载完成的文件
/// </summary>
/// <param name="absolutPath"></param>
/// <param name="data"></param>
/// <param name="fixPath"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 后台更新当前场景资源
/// </summary>
/// <param name="normalList"></param>
/// <param name="append"></param>
internal void BackDownloadCurSceneData(string[] normalList, bool append = false)
{
UpdateLog.WARN_LOG("Add cur scene resources");
AddDataList(normalList, DataLevel.CurScene, append);
}
/// <summary>
/// 后台更新下一场景资源
/// </summary>
/// <param name="preLoadList"></param>
/// <param name="append"></param>
internal void BackDownloadNextSceneData(string[] preLoadList, bool append = false)
{
AddDataList(preLoadList, DataLevel.NextScene, append);
}
/// <summary>
/// 下载场景资源
/// </summary>
/// <param name="mapID">要下载的场景ID</param>
/// <param name="current">是否当前场景</param>
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);
}
/// <summary>
/// 静默后台更新所有资源
/// </summary>
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;
}
}
}
/// <summary>
/// 总的后台下载资源大小
/// </summary>
/// <returns></returns>
public int GetTotalBaseResSize()
{
return _totalBaseResSize;
}
/// <summary>
/// 总的已下载大小
/// </summary>
/// <returns></returns>
public int GetTotalDownloadedSize()
{
return DownloadSpeeder.CurTotalSize;
//return BackDownload.TotalDownloadedSize;
}
/// <summary>
/// 获取下载速度
/// </summary>
/// <returns></returns>
public int GetDownloadSpeed()
{
return DownloadSpeeder.CalcSpeed();
}
/// <summary>
/// 初始化后台更新
/// </summary>
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);
}
}
}