Commit 19910d74 authored by hex's avatar hex

Optimized UnityFileDownloader.cs

parent 3e267a81
......@@ -46,7 +46,7 @@ public class UITexture : UIBasicSprite
protected override void OnStart()
{
base.OnStart();
if (mOutPath != "")
if (mOutPath != null && mOutPath != "")
{
mainTexture = GameTextureManager.get(mOutPath);
}
......
using System;
using System.Text;
using System.Collections.Generic;
using UnityEngine;
using YGOSharp.OCGWrapper.Enums;
......@@ -27,7 +28,7 @@ public class CardDescription : Servant
Program.camera_main_2d.ScreenToWorldPoint(new Vector3(-256, Screen.height / 2, 600)),
new Vector3(0, 0, 0),
true,
Program.ui_back_ground_2d
Program.ui_main_2d
);
picLoader = gameObject.AddComponent<cardPicLoader>();
picLoader.code = 0;
......@@ -453,52 +454,60 @@ public class CardDescription : Servant
List<string> Logs = new List<string>();
private StringBuilder logBuilder = new StringBuilder(1024); // 在类成员中创建一个 StringBuilder 实例,初始容量为1024字符,避免频繁扩容
public void mLog(string result)
{
Logs.Add(result);
string all = "";
for (int i = 0; i < Logs.Count; i++)
// 1. 添加新日志到列表
Logs.Add(result.Replace("\0", "")); // 在添加时就替换掉空字符
// 2. [可选但推荐] 控制日志列表的最大长度,防止无限增长
if (Logs.Count > 50) // 例如,最多保留50条日志
{
if (i == Logs.Count - 1)
{
all += Logs[i].Replace("\0", "");
}
else
{
all += Logs[i].Replace("\0", "") + "\n";
}
Logs.RemoveAt(0);
}
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), all);
// 3. 更新UI显示
UpdateLogDisplay();
// 4. 设置定时清除
Program.go(8000, clearOneLog);
}
void clearOneLog()
{
if (Logs.Count > 0)
if (Logs.Count > 0)
{
Logs.RemoveAt(0);
string all = "";
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);
UpdateLogDisplay();
}
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()
{
Program.notGo(clearOneLog);
Program.notGo(clearOneLog); // 取消所有待执行的 clearOneLog 任务
Logs.Clear();
UIHelper.trySetLableTextList(UIHelper.getByName(gameObject, "chat_"), "");
UpdateLogDisplay(); // 清空列表后,调用一次更新方法来清空UI
}
}
......@@ -552,7 +552,7 @@ public class Program : MonoBehaviour
string cardsUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/cards.cdb";
string cardsPath = Path.Combine(dbDir, "cards.cdb");
yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync(
UnityFileDownloader.DownloadFileWithHeadCheck(
cardsUrl,
cardsPath,
(success) =>
......@@ -570,7 +570,7 @@ public class Program : MonoBehaviour
string lflistUrl = "https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/lflist.conf";
string lflistPath = Path.Combine(dbDir, "lflist.conf");
yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync(
UnityFileDownloader.DownloadFileWithHeadCheck(
lflistUrl,
lflistPath,
(success) =>
......@@ -588,7 +588,7 @@ public class Program : MonoBehaviour
"https://cdn02.moecube.com:444/koishipro/ygopro-database/zh-CN/strings.conf";
string stringsPath = Path.Combine(dbDir, "strings.conf");
yield return StartCoroutine(
UnityFileDownloader.DownloadFileAsync(
UnityFileDownloader.DownloadFileWithHeadCheck(
stringsUrl,
stringsPath,
(success) =>
......
......@@ -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)
{
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