Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,638 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XGame
|
||||
{
|
||||
class UpdateModule : MonoBehaviour
|
||||
{
|
||||
public static UpdateModule Instance;
|
||||
public class ResInfo
|
||||
{
|
||||
//public string fileName;
|
||||
public string md5;
|
||||
public string md5Path;
|
||||
public int pack;
|
||||
public int priority;
|
||||
public int size;
|
||||
}
|
||||
|
||||
class PackWairDownList
|
||||
{
|
||||
public List<string> list = new List<string>();
|
||||
public int fileSize = 0;
|
||||
public string md5 = "";
|
||||
public bool isChange = false;
|
||||
}
|
||||
#if UNITY_ANDROID
|
||||
static string sPlatform = "android";
|
||||
#elif UNITY_IOS
|
||||
static string sPlatform = "ios";
|
||||
#else
|
||||
static string sPlatform = "pc";
|
||||
#endif
|
||||
|
||||
GameObject m_MainObj;
|
||||
//更新相关
|
||||
string UpdateServer;//
|
||||
string UpdatePath;
|
||||
string ServerListName = "files";
|
||||
string UpdateListName = "updatefiles";
|
||||
string TempListName = "tempfiles";
|
||||
private Dictionary<string, ResInfo> m_gameResDict = new Dictionary<string, ResInfo>();
|
||||
private Dictionary<string, ResInfo> m_localResDict = new Dictionary<string, ResInfo>();
|
||||
private Dictionary<string, ResInfo> m_tempResDict = new Dictionary<string, ResInfo>();
|
||||
private PackWairDownList[] m_packWairDownList = new PackWairDownList[10];
|
||||
|
||||
private int m_wairDownCount = 0;
|
||||
private int m_downDownCount = 0;
|
||||
//private bool m_bHotfix = false;
|
||||
|
||||
string m_sNewMD5;
|
||||
string m_sOldMD5;
|
||||
//bool m_bChange = false;
|
||||
|
||||
//UI 相关
|
||||
Slider m_sliderUpdate;
|
||||
TextMeshProUGUI m_textUpdate;
|
||||
XProgress m_Proc;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
#if UNITY_WEBGL
|
||||
UpdatePath = $"{Application.streamingAssetsPath}/";
|
||||
UpdateServer = $"{Application.streamingAssetsPath}/";
|
||||
#else
|
||||
UpdatePath = Application.persistentDataPath + "/";
|
||||
UpdateServer = $"{XGame.AppConst.UpdateServer}{sPlatform}/";//$"http://127.0.0.1/update/{sPlatform}/"; //
|
||||
#endif
|
||||
m_Proc = new XProgress();
|
||||
Init();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
m_packWairDownList[i] = new PackWairDownList();
|
||||
}
|
||||
|
||||
/*/Test
|
||||
//默认Main预设会直接挂好,直接使用下面的Update组件
|
||||
GameObject sliderObj = GameObject.Find("Main(Clone)/Update/Slider");//Base");//
|
||||
if (sliderObj != null)
|
||||
{
|
||||
m_sliderUpdate = sliderObj.transform.GetComponent<Slider>();
|
||||
}
|
||||
m_textUpdate = GameObject.Find("Main(Clone)/Update/Text").transform.GetComponent<TextMeshProUGUI>();
|
||||
//*/
|
||||
}
|
||||
|
||||
|
||||
public string GetResMD5()
|
||||
{
|
||||
return m_sNewMD5;
|
||||
}
|
||||
//设置资源管理器的文件列表hash 字典
|
||||
public void SetAllResHash()
|
||||
{
|
||||
if (m_gameResDict.Count == 0)
|
||||
{//还未加载file.txt
|
||||
LoadServerResourceMap();
|
||||
}
|
||||
string str;
|
||||
XResLoader.m_ResHash.Clear();
|
||||
foreach (var dic in m_gameResDict)
|
||||
{
|
||||
//保存UpdatePath/res
|
||||
Hash128 hash = Hash128.Parse(dic.Value.md5);
|
||||
XResLoader.m_ResHash[$"{AppConst.UpdatePath}{dic.Key}"] = hash;
|
||||
str = hash.ToString();
|
||||
}
|
||||
}
|
||||
public void AddResHash(Dictionary<string, ResInfo> resList)
|
||||
{
|
||||
foreach (var dic in resList)
|
||||
{
|
||||
//保存UpdatePath/res
|
||||
Hash128 hash = Hash128.Parse(dic.Value.md5);
|
||||
XResLoader.m_ResHash[$"{AppConst.UpdatePath}{dic.Key}"] = hash;
|
||||
}
|
||||
}
|
||||
#if UNITY_WEBGL
|
||||
public IEnumerator UpdateResAllWebGL(System.Action onDownloadComplete)
|
||||
{
|
||||
Dictionary<string, string> dicFilelist = new Dictionary<string, string>();
|
||||
|
||||
string downloadServer = UpdateServer;
|
||||
UnityWebRequest uwr = UnityWebRequest.Get($"{downloadServer}updatever.txt");
|
||||
yield return uwr.SendWebRequest();
|
||||
if (uwr.downloadHandler.isDone && uwr.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
m_sNewMD5 = uwr.downloadHandler.text;
|
||||
int npos = m_sNewMD5.IndexOf(',');
|
||||
if (npos != -1)//兼容单双md5
|
||||
m_sNewMD5 = m_sNewMD5.Substring(npos+1, m_sNewMD5.Length - npos -1);
|
||||
Debug.Log($"Download DataFile {m_sNewMD5} OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogErrorFormat($"{downloadServer}updatever.txt is not exists");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public IEnumerator UpdateResAll(System.Action onDownloadComplete)
|
||||
{
|
||||
//检查更新
|
||||
string sNewMD5File = $"{UpdatePath}updatever.txt";
|
||||
string sOldMD5File = $"{UpdatePath}ver.txt";
|
||||
if (File.Exists(sNewMD5File))
|
||||
{
|
||||
m_sNewMD5 = File.ReadAllText(sNewMD5File);
|
||||
int npos = m_sNewMD5.IndexOf(',');
|
||||
if (npos != -1)//兼容单双md5
|
||||
m_sNewMD5 = m_sNewMD5.Substring(npos + 1, m_sNewMD5.Length - npos - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//直接结束
|
||||
if(onDownloadComplete != null)
|
||||
onDownloadComplete();
|
||||
yield break;
|
||||
}
|
||||
if (File.Exists(sOldMD5File))
|
||||
{
|
||||
m_sOldMD5 = File.ReadAllText(sOldMD5File);
|
||||
}
|
||||
else
|
||||
{//无文件,说明是第一次需要都更新
|
||||
//m_bChange = true;
|
||||
}
|
||||
if (m_sNewMD5 != m_sOldMD5)
|
||||
{
|
||||
//m_bChange = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//无差异直接结束
|
||||
if (onDownloadComplete != null)
|
||||
onDownloadComplete();
|
||||
yield break;
|
||||
}
|
||||
yield return DownLoadAssets(onDownloadComplete);
|
||||
}
|
||||
|
||||
//进度变化的回调
|
||||
void UpdateProcess(int curFinish, int totalNum)
|
||||
{
|
||||
if(totalNum > 0)
|
||||
m_Proc.Set(curFinish * 100 / totalNum);
|
||||
//if(m_sliderUpdate != null)
|
||||
// m_sliderUpdate.value = curFinish;
|
||||
}
|
||||
void OnFileDownloadBegin(string filename, int data)
|
||||
{
|
||||
}
|
||||
void WriteVerFile()
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter($"{UpdatePath}ver.txt"))
|
||||
{
|
||||
sw.WriteLine(m_sNewMD5);
|
||||
}
|
||||
}
|
||||
IEnumerator DownLoadAssets(Action onDownloadComplete)
|
||||
{
|
||||
bool isVerChange = true;
|
||||
string[] sNewMd5s = m_sNewMD5.Split(',');
|
||||
string[] sOldMd5s = { "SDFASD123SFDSerw","gagfewr21dsfa" };
|
||||
if(!string.IsNullOrEmpty(m_sOldMD5))
|
||||
sOldMd5s = m_sOldMD5.Split(',');
|
||||
if (sNewMd5s[0] == sOldMd5s[0])
|
||||
{//资源md5相同,写ver更新结束
|
||||
WriteVerFile();
|
||||
onDownloadComplete();
|
||||
yield break;
|
||||
}
|
||||
//更新流程
|
||||
//获得版本号updatever.txt,对比本地ver.txt
|
||||
//yield return CheckPackage(UpdateServer, "updatever.txt", "ver.txt", (isChange, newmd5) =>
|
||||
//{
|
||||
// isVerChange = isChange;
|
||||
// m_packWairDownList[0].md5 = newmd5;
|
||||
// m_packWairDownList[0].isChange = isChange;
|
||||
//});
|
||||
m_packWairDownList[0].md5 = sNewMd5s[0];
|
||||
m_packWairDownList[0].isChange = true;
|
||||
//Debug.Log($"Update Res List Begin : {sNewMd5s[0]}");
|
||||
if (isVerChange)
|
||||
{
|
||||
m_gameResDict.Clear();
|
||||
m_localResDict.Clear();
|
||||
m_tempResDict.Clear();
|
||||
//有改变,需要下载并对比列表文件
|
||||
yield return DownloadFile(UpdateServer, $"{ServerListName}.txt", result =>
|
||||
{
|
||||
if (result > 0)
|
||||
{
|
||||
System.DateTime dt = System.DateTime.Now;
|
||||
LoadServerResourceMap();
|
||||
Debug.LogFormat("LoadServerResourceMap {0} 耗时:{1}ms", ServerListName, (System.DateTime.Now - dt).TotalMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogFormat("File not exist : {0}{1}", UpdatePath, ServerListName);
|
||||
isVerChange = false;
|
||||
}
|
||||
});
|
||||
if (!isVerChange)//失败
|
||||
{
|
||||
onDownloadComplete();
|
||||
yield break;
|
||||
}
|
||||
yield return LoadPackageResourceMap();
|
||||
LoadLocalResourceMap();
|
||||
|
||||
int count = 1;
|
||||
foreach (var gameRes in m_gameResDict)
|
||||
{
|
||||
ResInfo localRes = null;
|
||||
if (m_localResDict.TryGetValue(gameRes.Key, out localRes) && localRes.md5 == gameRes.Value.md5)
|
||||
{
|
||||
//m_existFiles[gameRes.Key] = EExistLocation.Local;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_tempResDict.TryGetValue(gameRes.Key, out localRes) && localRes.md5 == gameRes.Value.md5)
|
||||
{
|
||||
//m_existFiles[gameRes.Key] = EExistLocation.Local;
|
||||
}
|
||||
else
|
||||
{
|
||||
var packList = m_packWairDownList[0];//暂时只用一份更新,无分包
|
||||
packList.list.Add(gameRes.Key);
|
||||
packList.fileSize += gameRes.Value.size;
|
||||
|
||||
}
|
||||
}
|
||||
//m_packSizeRecord[gameRes.Value.pack - 1] += gameRes.Value.size;
|
||||
UpdateProcess(count++, m_gameResDict.Count);
|
||||
}
|
||||
//m_sliderUpdate.maxValue = m_packWairDownList[0].list.Count;
|
||||
//m_sliderUpdate.minValue = 0;
|
||||
//m_sliderUpdate.value = 0;
|
||||
m_Proc.Set(0);
|
||||
//写入ver.txt文件(md5) 这样可以防止以后服务器没更新的时候还下载检查更新
|
||||
if (m_packWairDownList[0].fileSize <= 0)
|
||||
{
|
||||
WriteVerFile();
|
||||
isVerChange = false;
|
||||
m_packWairDownList[0].isChange = false;
|
||||
}
|
||||
//下载过程
|
||||
UnityWebRequest uwr;
|
||||
string downloadServer = UpdateServer;
|
||||
Debug.LogFormat("downloadServer : {0} Total:{1}", downloadServer, m_packWairDownList[0].list.Count);
|
||||
int i = 0;
|
||||
count = m_packWairDownList[0].list.Count;
|
||||
string tempListFile = UpdatePath + TempListName + ".txt";
|
||||
StreamWriter fs = null;
|
||||
if (count > 0)
|
||||
{
|
||||
fs = new StreamWriter(tempListFile, true);
|
||||
}
|
||||
while (i < count)
|
||||
{
|
||||
string namePath = m_packWairDownList[0].list[i];
|
||||
var path = downloadServer + namePath;
|
||||
string outfile = UpdatePath + namePath;
|
||||
|
||||
uwr = UnityWebRequest.Get(path);
|
||||
|
||||
#region 下列代码修改下载的方式 用于处理断点下载和堆内存峰值
|
||||
// by xl
|
||||
string tempFile = outfile + ".temp";
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
XDownloadHandler dh = new XDownloadHandler(outfile);
|
||||
dh.OnFinish = (int size) =>
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
if (m_gameResDict.TryGetValue(namePath, out ResInfo resInfo))
|
||||
{
|
||||
//没关闭流 可能写不完整
|
||||
fs?.WriteLine(string.Format("{{'{0}','{1}','{2}'}}",
|
||||
namePath, resInfo.md5, 1, resInfo.size));
|
||||
}
|
||||
++m_downDownCount;
|
||||
if (m_textUpdate)
|
||||
{
|
||||
int percent = 100 * m_downDownCount / count;
|
||||
m_textUpdate.text = $"{percent}%";//namePath;
|
||||
}
|
||||
UpdateProcess(m_downDownCount, m_wairDownCount);
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("File Miss : " + path);
|
||||
}
|
||||
};
|
||||
uwr.downloadHandler = dh;
|
||||
#endregion
|
||||
|
||||
yield return uwr.SendWebRequest();
|
||||
|
||||
if (uwr.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Debug.LogError("File Download Error : " + path);
|
||||
}
|
||||
|
||||
}
|
||||
//m_sliderUpdate.value = m_packWairDownList[0].list.Count;
|
||||
m_packWairDownList[0].list.Clear();
|
||||
m_packWairDownList[0].fileSize = 0;
|
||||
m_packWairDownList[0].isChange = false;
|
||||
//using (StreamWriter sw = new StreamWriter(string.Format("{0}ver.txt", UpdatePath)))
|
||||
//{
|
||||
// sw.WriteLine(m_packWairDownList[0].md5);
|
||||
//}
|
||||
WriteVerFile();
|
||||
|
||||
//if (pack <= 1)
|
||||
{
|
||||
fs?.Close();
|
||||
yield return DownloadFile(downloadServer, ServerListName + ".txt", result =>
|
||||
{
|
||||
if (result > 0)
|
||||
{
|
||||
if (File.Exists(tempListFile))
|
||||
{
|
||||
File.Delete(tempListFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogErrorFormat("{0} is not exists", downloadServer + ServerListName + ".txt");
|
||||
}
|
||||
});
|
||||
m_wairDownCount = 0;
|
||||
m_downDownCount = 0;
|
||||
//m_Proc.Set(100);
|
||||
//m_downEndFun(isDllUpdate ? 1 : 0);
|
||||
//yield break;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("Download Finish!");
|
||||
if(onDownloadComplete != null)
|
||||
onDownloadComplete();
|
||||
}
|
||||
|
||||
//协程下载文件
|
||||
IEnumerator DownloadFile(string downloadServer, string fileName, System.Action<int> onFinish)
|
||||
{
|
||||
UnityWebRequest uwr;
|
||||
//Logger.LogFormat("download ServerList {0}", downloadServer + fileName);
|
||||
uwr = UnityWebRequest.Get(downloadServer + fileName);
|
||||
// uwr.timeout = m_httpRequestTimeout;
|
||||
yield return uwr.SendWebRequest();
|
||||
if (uwr.downloadHandler.isDone && uwr.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
string outfile = UpdatePath + fileName;
|
||||
string dir = Path.GetDirectoryName(outfile);
|
||||
//if (!Directory.Exists(dir))
|
||||
//{
|
||||
// Directory.CreateDirectory(dir);
|
||||
//}
|
||||
if (File.Exists(outfile))
|
||||
File.Delete(outfile);
|
||||
File.WriteAllBytes(outfile, uwr.downloadHandler.data);
|
||||
onFinish(uwr.downloadHandler.data.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Logger.LogFormat("Download Failed {0}", downloadServer + fileName);
|
||||
onFinish(0);
|
||||
//if (RequestErrorCallback != null) { RequestErrorCallback("DownloadFile", uwr.error); }
|
||||
}
|
||||
}
|
||||
IEnumerator CheckPackage(string downloadServer, string fileName, string verName, System.Action<bool, string> onFinish)
|
||||
{
|
||||
yield return DownloadFile(downloadServer, fileName, result =>
|
||||
{
|
||||
bool ischange = true;
|
||||
string vermd51 = null, newmd51 = null;
|
||||
if (result > 0 && File.Exists(UpdatePath + fileName))
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(UpdatePath + fileName))
|
||||
{
|
||||
string line;
|
||||
line = sr.ReadLine();
|
||||
if (line != null || line != "")
|
||||
{
|
||||
newmd51 = line;
|
||||
}
|
||||
}
|
||||
if (File.Exists(UpdatePath + verName))
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(UpdatePath + verName))
|
||||
{
|
||||
string line;
|
||||
line = sr.ReadLine();
|
||||
if (line != null || line != "")
|
||||
{
|
||||
vermd51 = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newmd51 != null)
|
||||
{
|
||||
if (vermd51 != null && newmd51 == vermd51)
|
||||
{
|
||||
ischange = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ischange = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ischange = false;
|
||||
}
|
||||
onFinish(ischange, newmd51);
|
||||
});
|
||||
}
|
||||
|
||||
//加载包内文件
|
||||
IEnumerator LoadPackageResourceMap()
|
||||
{
|
||||
string content;
|
||||
//在协程里,加载完才往下走
|
||||
yield return XResLoader.OnLoadPackageFile($"{ServerListName}.txt", (data) =>
|
||||
{
|
||||
string str;
|
||||
if (data != null)
|
||||
{
|
||||
str = System.Text.Encoding.UTF8.GetString(data);
|
||||
TextAsset textAsset = new TextAsset(str);//Resources.Load<TextAsset>($"{ServerListName}.txt");
|
||||
|
||||
if (textAsset != null)
|
||||
{
|
||||
content = textAsset.text;
|
||||
LoadResourceMap(content, m_localResDict);
|
||||
}
|
||||
}
|
||||
Debug.LogFormat("{0} file(s) exist in game.", m_localResDict.Count);
|
||||
});
|
||||
|
||||
}
|
||||
void LoadLocalResourceMap()
|
||||
{
|
||||
string localListFile = UpdatePath + UpdateListName + ".txt";
|
||||
string content = "";
|
||||
if (File.Exists(localListFile))
|
||||
{
|
||||
content = File.ReadAllText(localListFile);
|
||||
LoadResourceMap(content, m_localResDict);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadTempResourceMap()
|
||||
{
|
||||
string tempListFile = UpdatePath + TempListName + ".txt";
|
||||
string content = "";
|
||||
if (File.Exists(tempListFile))
|
||||
{
|
||||
content = File.ReadAllText(tempListFile);
|
||||
//此处是为了修复 文件写入不完整的问题
|
||||
if (!string.IsNullOrEmpty(content) && !content.EndsWith("}"))
|
||||
{
|
||||
int lastIdx = content.LastIndexOf("}");
|
||||
content = content.Substring(0, lastIdx + 2);//包含换行
|
||||
File.WriteAllText(tempListFile, content);
|
||||
}
|
||||
LoadResourceMap(content, m_tempResDict);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadResourceMap(string content, Dictionary<string, ResInfo> resMap)
|
||||
{
|
||||
if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
Debug.LogWarningFormat("Can't load file_list");
|
||||
return;
|
||||
}
|
||||
string[] lines = content.Split('\n');
|
||||
if (lines == null)
|
||||
{
|
||||
Debug.LogWarningFormat("Can't load res_list, it is required!");
|
||||
return;
|
||||
}
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length < 2) { continue; }
|
||||
|
||||
string s = line.Substring(1, line.Length - 1 - 2); //去掉开头的{'和结尾的},
|
||||
s = s.Replace("\'", ""); //把lua的字符串包围符去掉.
|
||||
|
||||
string[] strs = s.Split(',');
|
||||
if (strs.Length > 2)
|
||||
{
|
||||
ResInfo resInfo = new ResInfo();
|
||||
resInfo.md5Path = strs[0];
|
||||
resInfo.md5 = strs[1];
|
||||
resInfo.size = int.Parse(strs[2]);
|
||||
resMap[strs[0]] = resInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarningFormat("invalid line: ", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadServerResourceMap()
|
||||
{
|
||||
string listPath = $"{UpdatePath}{ServerListName}.txt";
|
||||
if (!File.Exists(listPath))
|
||||
{//本地还没有下载过资源清单(首次启动 / 未触发增量更新),无缓存可读,安全跳过
|
||||
Debug.LogWarning($"LoadServerResourceMap skip, not found: {listPath}");
|
||||
return;
|
||||
}
|
||||
string content;//= ResourceLoader.instance.LoadAssetString(ServerListName + ".txt");//Android上读的是内部的文件
|
||||
byte[] data;
|
||||
long size;
|
||||
using (var stream = File.OpenRead(listPath))// _{ m_sNewMD5}
|
||||
{
|
||||
size = stream.Seek(0, SeekOrigin.End);
|
||||
data = new byte[size];
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.Read(data, 0, data.Length);
|
||||
content = System.Text.Encoding.UTF8.GetString(data);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
Debug.LogWarningFormat("LoadServerResourceMap Can't load file_list");
|
||||
}
|
||||
|
||||
string[] lines = content.Split('\n');
|
||||
//Debug.LogFormat("{0} lines in ServerListName", lines.Length);
|
||||
if (lines != null)
|
||||
{
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length < 2) { continue; }
|
||||
|
||||
//fileName, md5, size
|
||||
//{'ui/copy_fui.ab','2ca8dd785bf3e99decaab1f9e3e4cd22',1257},
|
||||
string s = line.Substring(1, line.Length - 1 - 2); //去掉开头的{'和结尾的},
|
||||
s = s.Replace("\'", ""); //把lua的字符串包围符去掉.
|
||||
|
||||
string[] strs = s.Split(',');
|
||||
if (strs.Length > 2)
|
||||
{
|
||||
ResInfo resInfo = new ResInfo();
|
||||
resInfo.md5Path = strs[0];
|
||||
resInfo.md5 = strs[1];
|
||||
resInfo.size = int.Parse(strs[2]);
|
||||
m_gameResDict[strs[0]] = resInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Logger.LogWarningFormat("invalid line: ", line);
|
||||
}
|
||||
}
|
||||
//Logger.LogFormat("{0} file(s) exist in game.", m_gameResDict.Count);
|
||||
}
|
||||
else
|
||||
{//失败
|
||||
//throw new InvalidResListException("Can't load server_res_list, it is required!");
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//m_Proc.Update();
|
||||
}
|
||||
|
||||
public XProgress GetProgress()
|
||||
{
|
||||
return m_Proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44860d1246d1f21489648010fb3d95d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
/// <summary>
|
||||
/// 用于处理文件下载
|
||||
/// </summary>
|
||||
internal class XDownloadHandler: DownloadHandlerScript
|
||||
{
|
||||
string m_SavePath = "";
|
||||
string m_TempFilePath = "";
|
||||
FileStream fs;
|
||||
|
||||
public long totalFileLen { get; private set; }
|
||||
public long downloadedFileLen { get; private set; }
|
||||
public string fileName { get; private set; }
|
||||
public string dirPath { get; private set; }
|
||||
|
||||
#region 事件
|
||||
|
||||
/// <summary>
|
||||
/// 每次下载到数据后回调进度
|
||||
/// </summary>
|
||||
public Action<float,float> OnProgress = null;
|
||||
|
||||
/// <summary>
|
||||
/// 当下载完成后回调下载的文件位置
|
||||
/// </summary>
|
||||
public Action<int> OnFinish = null;
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化下载句柄,定义每次下载的数据上限为1M
|
||||
/// </summary>
|
||||
/// <param name="filePath">保存到本地的文件路径</param>
|
||||
public XDownloadHandler(string filePath) : base(new byte[1024 * 1024])
|
||||
{
|
||||
m_SavePath = filePath.Replace('\\', '/');
|
||||
fileName = m_SavePath.Substring(m_SavePath.LastIndexOf('/') + 1);
|
||||
dirPath = m_SavePath.Substring(0, m_SavePath.LastIndexOf('/'));
|
||||
m_TempFilePath = Path.Combine(dirPath, fileName + ".temp");
|
||||
if (!Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
}
|
||||
|
||||
fs = new FileStream(m_TempFilePath, FileMode.Append, FileAccess.Write);
|
||||
downloadedFileLen = fs.Length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从网络获取数据时候的回调,每帧调用一次
|
||||
/// </summary>
|
||||
/// <param name="data">接收到的数据字节流,总长度为构造函数定义的200kb,并非所有的数据都是新的</param>
|
||||
/// <param name="dataLength">接收到的数据长度,表示data字节流数组中有多少数据是新接收到的,即0-dataLength之间的数据是刚接收到的</param>
|
||||
/// <returns>返回true为继续下载,返回false为中断下载</returns>
|
||||
protected override bool ReceiveData(byte[] data, int dataLength)
|
||||
{
|
||||
if (data == null || data.Length == 0)
|
||||
{
|
||||
Debug.LogFormat("【下载中】 下载文件{0}中,没有获取到数据,下载终止", fileName);
|
||||
return false;
|
||||
}
|
||||
fs?.Write(data, 0, dataLength);
|
||||
downloadedFileLen += dataLength;
|
||||
|
||||
OnProgress?.Invoke(downloadedFileLen, totalFileLen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当接受数据完成时的回调
|
||||
/// </summary>
|
||||
protected override void CompleteContent()
|
||||
{
|
||||
OnDispose();
|
||||
//Debug.LogFormat("【下载完成】 完成对{0}文件的下载,保存路径为{1}", fileName, m_SavePath);
|
||||
|
||||
if (File.Exists(m_TempFilePath))
|
||||
{
|
||||
if (File.Exists(m_SavePath))
|
||||
File.Delete(m_SavePath);
|
||||
File.Move(m_TempFilePath, m_SavePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogFormat("【下载失败】 下载文件{0}时失败", fileName);
|
||||
}
|
||||
OnFinish?.Invoke((int)downloadedFileLen);
|
||||
}
|
||||
|
||||
public void OnDispose()
|
||||
{
|
||||
fs?.Close();
|
||||
fs?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求下载时的第一个回调函数,会返回需要接收的文件总长度
|
||||
/// </summary>
|
||||
/// <param name="contentLength">如果是续传,则是剩下的文件大小;本地拷贝则是文件总长度</param>
|
||||
protected override void ReceiveContentLengthHeader(ulong contentLength)
|
||||
{
|
||||
if (contentLength == 0)
|
||||
{
|
||||
Debug.Log("【下载已经完成】");
|
||||
CompleteContent();
|
||||
}
|
||||
base.ReceiveContentLengthHeader(contentLength);
|
||||
totalFileLen = (long)contentLength + downloadedFileLen;
|
||||
}
|
||||
|
||||
public void ErrorDispose()
|
||||
{
|
||||
fs.Close();
|
||||
fs.Dispose();
|
||||
if (File.Exists(m_TempFilePath))
|
||||
{
|
||||
File.Delete(m_TempFilePath);
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
OnFinish = null;
|
||||
OnProgress = null;
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2419a3fbc53a804f98eddcce6dfb04d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user