Commit 19910d74 authored by hex's avatar hex

Optimized UnityFileDownloader.cs

parent 3e267a81
...@@ -46,7 +46,7 @@ public class UITexture : UIBasicSprite ...@@ -46,7 +46,7 @@ public class UITexture : UIBasicSprite
protected override void OnStart() protected override void OnStart()
{ {
base.OnStart(); base.OnStart();
if (mOutPath != "") if (mOutPath != null && mOutPath != "")
{ {
mainTexture = GameTextureManager.get(mOutPath); mainTexture = GameTextureManager.get(mOutPath);
} }
......
using System; using System;
using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using YGOSharp.OCGWrapper.Enums; using YGOSharp.OCGWrapper.Enums;
...@@ -27,7 +28,7 @@ public class CardDescription : Servant ...@@ -27,7 +28,7 @@ public class CardDescription : Servant
Program.camera_main_2d.ScreenToWorldPoint(new Vector3(-256, Screen.height / 2, 600)), Program.camera_main_2d.ScreenToWorldPoint(new Vector3(-256, Screen.height / 2, 600)),
new Vector3(0, 0, 0), new Vector3(0, 0, 0),
true, true,
Program.ui_back_ground_2d Program.ui_main_2d
); );
picLoader = gameObject.AddComponent<cardPicLoader>(); picLoader = gameObject.AddComponent<cardPicLoader>();
picLoader.code = 0; picLoader.code = 0;
...@@ -453,52 +454,60 @@ public class CardDescription : Servant ...@@ -453,52 +454,60 @@ public class CardDescription : Servant
List<string> Logs = new List<string>(); List<string> Logs = new List<string>();
private StringBuilder logBuilder = new StringBuilder(1024); // 在类成员中创建一个 StringBuilder 实例,初始容量为1024字符,避免频繁扩容
public void mLog(string result) public void mLog(string result)
{ {
Logs.Add(result); // 1. 添加新日志到列表
string all = ""; Logs.Add(result.Replace("\0", "")); // 在添加时就替换掉空字符
for (int i = 0; i < Logs.Count; i++)
// 2. [可选但推荐] 控制日志列表的最大长度,防止无限增长
if (Logs.Count > 50) // 例如,最多保留50条日志
{ {
if (i == Logs.Count - 1) Logs.RemoveAt(0);
{
all += Logs[i].Replace("\0", "");
}
else
{
all += Logs[i].Replace("\0", "") + "\n";
}
} }
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), all);
// 3. 更新UI显示
UpdateLogDisplay();
// 4. 设置定时清除
Program.go(8000, clearOneLog); Program.go(8000, clearOneLog);
} }
void clearOneLog() void clearOneLog()
{ {
if (Logs.Count > 0) if (Logs.Count > 0)
{ {
Logs.RemoveAt(0); Logs.RemoveAt(0);
string all = ""; UpdateLogDisplay();
foreach (var item in Logs)
{
all += item + "\n";
}
try
{
all = all.Substring(0, all.Length - 1);
}
catch (System.Exception e) { }
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), all);
} }
else }
// 提取出的公共方法,用于更新UI
private void UpdateLogDisplay()
{
// 1. 清空 StringBuilder
logBuilder.Length = 0;
// 2. 高效地构建日志字符串
for (int i = 0; i < Logs.Count; i++)
{
logBuilder.AppendLine(Logs[i]); // AppendLine 会自动在末尾添加换行符
}
// 3. 将最终结果设置到UI控件
// getByName 可能会有性能开销,如果这个方法被非常频繁调用,可以考虑缓存这个GameObject
GameObject chatObject = UIHelper.getByName(gameObject, "chat_");
if (chatObject != null)
{ {
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), ""); UIHelper.trySetLableTextList(chatObject, logBuilder.ToString());
} }
} }
public void clearAllLog() public void clearAllLog()
{ {
Program.notGo(clearOneLog); Program.notGo(clearOneLog); // 取消所有待执行的 clearOneLog 任务
Logs.Clear(); Logs.Clear();
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), ""); UpdateLogDisplay(); // 清空列表后,调用一次更新方法来清空UI
} }
} }
...@@ -552,7 +552,7 @@ public class Program : MonoBehaviour ...@@ -552,7 +552,7 @@ public class Program : MonoBehaviour
string cardsUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/cards.cdb"; string cardsUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/cards.cdb";
string cardsPath = Path.Combine(dbDir, "cards.cdb"); string cardsPath = Path.Combine(dbDir, "cards.cdb");
yield return StartCoroutine( yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync( UnityFileDownloader.DownloadFileWithHeadCheck(
cardsUrl, cardsUrl,
cardsPath, cardsPath,
(success) => (success) =>
...@@ -570,7 +570,7 @@ public class Program : MonoBehaviour ...@@ -570,7 +570,7 @@ public class Program : MonoBehaviour
string lflistUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/lflist.conf"; string lflistUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/lflist.conf";
string lflistPath = Path.Combine(dbDir, "lflist.conf"); string lflistPath = Path.Combine(dbDir, "lflist.conf");
yield return StartCoroutine( yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync( UnityFileDownloader.DownloadFileWithHeadCheck(
lflistUrl, lflistUrl,
lflistPath, lflistPath,
(success) => (success) =>
...@@ -588,7 +588,7 @@ public class Program : MonoBehaviour ...@@ -588,7 +588,7 @@ public class Program : MonoBehaviour
"https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/strings.conf"; "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/strings.conf";
string stringsPath = Path.Combine(dbDir, "strings.conf"); string stringsPath = Path.Combine(dbDir, "strings.conf");
yield return StartCoroutine( yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync( UnityFileDownloader.DownloadFileWithHeadCheck(
stringsUrl, stringsUrl,
stringsPath, stringsPath,
(success) => (success) =>
......
...@@ -86,6 +86,104 @@ public class UnityFileDownloader ...@@ -86,6 +86,104 @@ public class UnityFileDownloader
} }
} }
/// <summary>
/// 检查文件版本,如果不是最新则下载。
/// 最终结果统一为成功(true)或失败(false)。
/// </summary>
/// <param name="url">文件下载地址</param>
/// <param name="filePath">文件本地存储路径</param>
/// <param name="onComplete">完成时的回调。true表示成功(已是最新或已下载),false表示失败。</param>
/// <param name="onProgress">下载过程中的进度回调(仅在需要下载时触发)</param>
public static IEnumerator DownloadFileWithHeadCheck(
string url,
string filePath,
Action<bool> onComplete,
Action<float> onProgress = null) // 移除了onProgress的默认值null,以兼容旧版C#
{
string etagFilePath = filePath + ".etag";
string localEtag = null;
bool localFileExists = File.Exists(filePath);
// 1. 读取本地ETag(如果存在)
if (File.Exists(etagFilePath))
{
try
{
localEtag = File.ReadAllText(etagFilePath);
}
catch(Exception e)
{
Debug.LogWarning(string.Format("读取本地ETag文件失败: {0}. Error: {1}. 将强制更新。", etagFilePath, e.Message));
localEtag = null; // 读取失败则当做不存在
}
}
// 2. 发送HEAD请求获取服务器ETag
Debug.Log(string.Format("[HEAD] 正在检查: {0}", Path.GetFileName(filePath)));
UnityWebRequest headRequest = UnityWebRequest.Head(url);
yield return headRequest.SendWebRequest();
if (headRequest.isNetworkError || headRequest.isHttpError)
{
Debug.LogError(string.Format("[HEAD] 请求失败: {0}\n错误: {1}", url, headRequest.error));
if (onComplete != null) onComplete.Invoke(false);
yield break;
}
string serverEtag = headRequest.GetResponseHeader("ETag");
if (string.IsNullOrEmpty(serverEtag))
{
Debug.LogError(string.Format("[HEAD] 服务器未提供ETag头信息: {0}", url));
if (onComplete != null) onComplete.Invoke(false);
yield break;
}
Debug.Log(string.Format("版本比较: Local ETag='{0}', Server ETag='{1}'", localEtag, serverEtag));
// 3. 比较ETag
if (localFileExists && !string.IsNullOrEmpty(localEtag) && localEtag.Equals(serverEtag))
{
Debug.Log(string.Format("[OK] 文件已是最新版本: {0}", Path.GetFileName(filePath)));
if (onComplete != null) onComplete.Invoke(true); // 已是最新,也算成功
yield break;
}
// 4. ETag不匹配或本地文件不存在,执行下载
Debug.Log(string.Format("发现新版本或本地文件不存在,开始下载: {0}", Path.GetFileName(filePath)));
// --- Chaining Coroutine to get the result ---
bool downloadSucceeded = false;
// 创建一个回调,用于从DownloadFileAsync获取其执行结果
Action<bool> downloadCallback = delegate(bool success)
{
downloadSucceeded = success;
};
// 调用下载协程,并等待它完成
yield return DownloadFileAsync(url, filePath, downloadCallback, onProgress);
// --- Coroutine finished, now check the result ---
// 5. 下载完成后,更新ETag并回调
if (downloadSucceeded)
{
try
{
File.WriteAllText(etagFilePath, serverEtag);
Debug.Log(string.Format("成功保存新的ETag到: {0}", etagFilePath));
if (onComplete != null) onComplete.Invoke(true); // 下载并保存ETag成功
}
catch(Exception e)
{
Debug.LogError(string.Format("保存ETag文件失败: {0}. Error: {1}", etagFilePath, e.Message));
if (onComplete != null) onComplete.Invoke(false); // ETag保存失败,算整体失败
}
}
else
{
// DownloadFileAsync 内部已经打印了错误日志
if (onComplete != null) onComplete.Invoke(false); // 下载失败
}
}
private static int GetTimeoutForFile(string filename) private static int GetTimeoutForFile(string filename)
{ {
string extension = Path.GetExtension(filename).ToLower(); string extension = Path.GetExtension(filename).ToLower();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment