Commit 2d415ad1 authored by hex's avatar hex

增加立绘资源下载

parent 2026bcad
Pipeline #40002 failed
......@@ -3,15 +3,26 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using Unity.Mathematics;
using UnityEngine;
public class Menu : WindowServantSP
{
// [新增] 用于防止重复点击下载的标志位
private bool isDownloadingSuperPre = false;
private bool isPreDownloading = false;
private bool isClouseupDownloading = false;
private bool _isCancellationRequested = false;
private const string CloseupDirectory = "picture/closeup";
// 用于在协程间传递结果的成员变量
private int _closeupSuccessCount;
private int _closeupFailureCount;
private List<string> _pendingCloseupDownloads;
private Coroutine _currentDownloadCoroutine = null;
//GameObject screen;
public override void initialize()
......@@ -28,7 +39,7 @@ public class Menu : WindowServantSP
UIHelper.registEvent(gameObject, "exit_", onClickExit);
UIHelper.registEvent(gameObject, "joinQQ_", onClickJoinQQ);
// 将 onClickDownload 的事件注册指向我们新的实现
UIHelper.registEvent(gameObject, "supreCards_", onClickDownloadSuperPre);
UIHelper.registEvent(gameObject, "supreCards_", onClickUpdateResources);
//(new Thread(up)).Start();
}
......@@ -76,15 +87,290 @@ public class Menu : WindowServantSP
}
}
private void onClickUpdateResources()
{
if (isClouseupDownloading)
{
// 如果下载正在进行,弹出一个非阻塞的选择框,而不是简单打印文字
RMSshow_yesOrNo(
"HANDLE_ONGOING_DOWNLOAD", // 新的哈希码,用于区分事件
$"立绘下载正在后台进行中...\n进度 {_closeupSuccessCount}/{_pendingCloseupDownloads.Count}\n点击”是“继续下载\n点击”否“取消下载",
new messageSystemValue { value = "continue", hint = "继续下载" }, // 选项1:让它继续
new messageSystemValue { value = "cancel", hint = "取消下载" } // 选项2:取消它
);
return; // 阻止后续逻辑执行
}
else if (isPreDownloading)
{
RMSshow_onlyYes(
"HANDLE_ONGOING_DOWNLOAD", // 新的哈希码,用于区分事件
"先行卡下载正在后台进行中...",
new messageSystemValue { value = "continue", hint = "继续下载" } // 选项1:让它继续
);
return;
}
// 如果没有下载任务,则执行原有的逻辑
var options = new List<messageSystemValue>
{
new messageSystemValue { value = "super_pre", hint = "更新超先行卡" },
new messageSystemValue { value = "closeup", hint = "下载/更新立绘" },
new messageSystemValue { value = "cancel", hint = "取消" }
};
RMSshow_singleChoice("UPDATE_RESOURCES", options);
}
public override void ES_RMS(string hashCode, List<messageSystemValue> result)
{
base.ES_RMS(hashCode, result);
if (hashCode == "RMSshow_onlyYes")
switch (hashCode)
{
case "UPDATE_RESOURCES":
string choice = result[0].value;
if (choice == "super_pre")
{
Program.I().StartCoroutine(DownloadAndApplySuperPrePackCoroutine());
}
else if (choice == "closeup")
{
Program.I().StartCoroutine(DownloadCloseupsCoroutine());
}
break;
case "CONFIRM_CLOSEUP_DOWNLOAD": // 用户确认下载N个文件
if (result[0].value == "yes")
{
StartCloseupDownload();
}
else
{
isClouseupDownloading = false;
_pendingCloseupDownloads = null;
Program.PrintToChat("操作已取消。");
}
break;
case "CANCEL_DOWNLOAD_TASK":
_isCancellationRequested = true;
Program.PrintToChat("正在取消下载,请稍候...");
RMSshow_clear();
break;
case "HANDLE_ONGOING_DOWNLOAD":
if (result[0].value == "cancel")
{
// 如果用户选择取消
if (_currentDownloadCoroutine != null)
{
_isCancellationRequested = true;
Program.PrintToChat("正在请求取消下载,请稍候...");
}
}
break;
case "RMSshow_onlyYes":
Application.OpenURL(upurl);
break;
}
}
#region 立绘下载 (已应用包装器模式)
/// <summary>
/// [准备阶段] 检查立绘资源并向用户确认
/// </summary>
private IEnumerator DownloadCloseupsCoroutine()
{
if (isClouseupDownloading) yield break;
isClouseupDownloading = true;
string downloadsDir = "downloads";
if (!Directory.Exists(downloadsDir)) Directory.CreateDirectory(downloadsDir);
List<string> filesToDownload = null;
string filelistInDownloadPath = Path.Combine(downloadsDir, "filelist.txt");
Program.PrintToChat("正在检查立绘资源列表...");
bool listDownloaded = false;
yield return Program.I().StartCoroutine(UnityFileDownloader.DownloadFileWithHeadCheck(
"https://cdntx.moecube.com/ygopro2-closeup/filelist.txt",
filelistInDownloadPath,
(success) => { listDownloaded = success; }
));
if (!listDownloaded)
{
Program.PrintToChat("获取立绘列表失败,请检查网络或稍后再试。");
isClouseupDownloading = false;
_pendingCloseupDownloads = null;
yield break;
}
Program.PrintToChat("解析文件列表并与本地文件比对...");
try
{
if (!Directory.Exists(CloseupDirectory)) Directory.CreateDirectory(CloseupDirectory);
var serverFiles = File.ReadAllLines(filelistInDownloadPath).Where(line => !string.IsNullOrWhiteSpace(line));
var localFiles = new HashSet<string>(Directory.GetFiles(CloseupDirectory, "*.png").Select(Path.GetFileName));
// 有一张图片是 .PNG 大写结尾的 39272762.PNG iOS区分大小写,统一兼容一下小写保存
filesToDownload = serverFiles.Where(f => !localFiles.Contains(f.ToLowerInvariant())).ToList();
}
catch (Exception e)
{
Program.PrintToChat($"处理文件列表时发生错误: {e.Message}");
isClouseupDownloading = false;
_pendingCloseupDownloads = null;
yield break;
}
if (filesToDownload.Count == 0)
{
Program.PrintToChat("立绘资源已是最新,无需下载。");
isClouseupDownloading = false;
_pendingCloseupDownloads = null;
yield break;
}
if (filesToDownload.Count == 1)
{
Program.PrintToChat($"{filesToDownload[0]}");
}
_pendingCloseupDownloads = filesToDownload;
string confirmationMessage = $"发现 {filesToDownload.Count} 个新立绘需要下载。\n这可能会消耗较多时间和数据流量,是否继续?";
RMSshow_yesOrNo(
"CONFIRM_CLOSEUP_DOWNLOAD",
confirmationMessage,
new messageSystemValue { value = "yes" },
new messageSystemValue { value = "no" }
);
}
private void StartCloseupDownload()
{
// 双重检查,确保有东西可下且没有任务在进行
if (_pendingCloseupDownloads == null || _pendingCloseupDownloads.Count == 0 || _currentDownloadCoroutine != null)
{
Application.OpenURL(upurl);
isClouseupDownloading = false;
return;
}
// 1. 设置初始状态
isClouseupDownloading = true; // 保持这个标记,用于重复点击判断
_isCancellationRequested = false;
_closeupSuccessCount = 0;
_closeupFailureCount = 0;
// 2. 打印开始信息
Program.PrintToChat($"开始后台下载 {_pendingCloseupDownloads.Count} 个立绘...");
// 3. 启动 "工作者" 协程,并将其实例存起来
_currentDownloadCoroutine = Program.I().StartCoroutine(ExecuteCloseupDownload_Worker());
}
/// <summary>
/// [处理器] 立绘下载的包装器协程
/// </summary>
private IEnumerator ExecuteCloseupDownload()
{
// 1. 设置初始状态
_closeupSuccessCount = 0;
_closeupFailureCount = 0;
RMSshow_onlyYes("CANCEL_DOWNLOAD_TASK", "下载进行中...", new messageSystemValue { hint = "确认" });
var worker = ExecuteCloseupDownload_Worker();
// 2. 监视并执行工作者
while (true)
{
try
{
if (!worker.MoveNext()) break;
}
catch (Exception e)
{
Program.PrintToChat($"下载过程中发生严重错误: {e.Message}");
break;
}
yield return worker.Current;
}
// 3. 最终清理
RMSshow_clear();
_isCancellationRequested = false;
isClouseupDownloading = false;
_pendingCloseupDownloads = null;
// 4. 最终报告
if (_closeupFailureCount > 0)
{
Program.PrintToChat($"下载完成。成功: {_closeupSuccessCount},失败: {_closeupFailureCount}。您可以稍后重新运行以下载失败的文件。");
}
else if (_closeupSuccessCount > 0)
{
Program.PrintToChat($"下载完成!共 {_closeupSuccessCount} 个新立绘已成功下载。");
}
}
/// <summary>
/// [工作者] 立绘下载的实际工作协程
/// </summary>
private IEnumerator ExecuteCloseupDownload_Worker()
{
var filesToDownload = _pendingCloseupDownloads;
var totaToDownloadCount = filesToDownload.Count;
double nextReportPercentage = 0;
for (int i = 0; i < totaToDownloadCount; i++)
{
if (_isCancellationRequested)
{
Program.PrintToChat("下载任务已被用户取消。");
break; // 跳出循环,进入最终清理阶段
}
string filename = filesToDownload[i];
string downloadUrl = "https://cdntx.moecube.com/ygopro2-closeup/closeup/" + filename;
string localPath = Path.Combine(CloseupDirectory, filename.ToLowerInvariant());
float currentProgress = (float)(i + 1) / totaToDownloadCount * 100f;
// 如果当前进度超过了我们设定的下一个报告点
if (currentProgress >= nextReportPercentage)
{
Program.PrintToChat($"下载进度: {nextReportPercentage}%, {_closeupSuccessCount} / {totaToDownloadCount}");
nextReportPercentage += 10;
}
bool singleFileDownloaded = false;
yield return Program.I().StartCoroutine(UnityFileDownloader.DownloadFileAsync(
downloadUrl,
localPath,
(success) => { singleFileDownloaded = success; }
));
if (singleFileDownloaded) _closeupSuccessCount++;
else _closeupFailureCount++;
}
// --- 核心优化点 4: 下载结束后,在这里统一清理状态和报告结果 ---
string finalMessage;
if (_closeupFailureCount > 0)
{
finalMessage = $"下载完成。成功: {_closeupSuccessCount},失败: {_closeupFailureCount}。可稍后重试。";
}
else
{
finalMessage = $"下载完成!共 {_closeupSuccessCount} 个新立绘已成功下载。";
}
Program.PrintToChat(finalMessage);
// 重置所有状态,为下一次下载做准备
isClouseupDownloading = false;
_isCancellationRequested = false;
_pendingCloseupDownloads = null;
_currentDownloadCoroutine = null; // 清理协程引用
}
#endregion
bool outed = false;
public override void preFrameFunction()
......@@ -157,7 +443,7 @@ public class Menu : WindowServantSP
void onClickDownloadSuperPre()
{
if (isDownloadingSuperPre)
if (isPreDownloading)
{
Program.PrintToChat("正在处理中,请稍候...");
return;
......@@ -168,7 +454,7 @@ public class Menu : WindowServantSP
private IEnumerator DownloadAndApplySuperPrePackCoroutine()
{
isDownloadingSuperPre = true;
isPreDownloading = true;
var workerEnumerator = DownloadAndApplySuperPrePack_Worker();
......@@ -193,7 +479,7 @@ public class Menu : WindowServantSP
yield return current;
}
isDownloadingSuperPre = false;
isPreDownloading = false;
}
private IEnumerator DownloadAndApplySuperPrePack_Worker()
......@@ -250,18 +536,18 @@ public class Menu : WindowServantSP
if (newVersionDownloaded)
{
Program.PrintToChat("下载完成,开始应用更新...");
yield return null;
yield return null;
Program.PrintToChat("正在清理旧文件...");
// 同步操作,如果失败会抛出异常
ClearDirectory(expansionsDir);
yield return null;
yield return null;
Program.PrintToChat("正在解压新文件...");
byte[] ypkData = File.ReadAllBytes(ypkFilePathInDownloads);
// 同步操作,如果失败会抛出异常
Program.I().ExtractZipFile(ypkData, expansionsDir);
Program.PrintToChat("更新成功!请【重启游戏】以使改动完全生效。");
}
else
......@@ -284,7 +570,7 @@ public class Menu : WindowServantSP
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
dir.Delete(true);
dir.Delete(true);
}
}
......
......@@ -403,9 +403,32 @@ public class Program : MonoBehaviour
Config.initialize("config/config.conf");
// [新增] 封装文件加载逻辑,避免重复检查
// 封装文件加载逻辑,避免重复检查
LoadDatabaseFile("cards.cdb", (path) => YGOSharp.CardsManager.initialize(path));
LoadDatabaseFile("strings.conf", (path) => GameStringManager.initialize(path));
// 创建文件夹
if (!Directory.Exists("expansions"))
{
try
{
Directory.CreateDirectory("expansions");
}
catch
{
}
}
if (!Directory.Exists("replay"))
{
try
{
Directory.CreateDirectory("replay");
}
catch
{
}
}
// lflist的加载顺序有特殊性,单独处理
if (File.Exists("expansions/lflist.conf"))
......
......@@ -554,7 +554,8 @@ public class DeckManager : ServantWithCardDescription
// 【核心修改】计算两个面板共同的、正确的垂直中心点Y坐标
// 这个公式必须与 applyShowArrangement() 中使用的完全一致!
float sharedCenterY = safeArea.y + (searchPanelTexture.height / 2f);
float visibleTargetY = safeArea.y + (searchPanelTexture.height / 2f);
visibleTargetY -= 40;
// 计算详细搜索框“可见时”的目标 X 坐标中心点
// 逻辑:安全区右边缘 - 主面板宽度 - 详细面板宽度的一半(考虑缩放)
......@@ -570,7 +571,7 @@ public class DeckManager : ServantWithCardDescription
if (detailShowed)
{
// **显示时**: 移动到 safeArea 内,主搜索框左侧,并使用共享的Y坐标
targetScreenPos = new Vector3(visibleTargetX, sharedCenterY, 0);
targetScreenPos = new Vector3(visibleTargetX, visibleTargetY, 0);
// 更新底部Bar的右边距,使其避开两个面板的总宽度
reShowBar(0, searchPanelActualWidth + (DETAILED_SEARCH_PANEL_WIDTH * scaleFactor));
......@@ -2306,9 +2307,9 @@ public class DeckManager : ServantWithCardDescription
{
// UnityEngine.Debug.Log(e);
}
List<YGOSharp.Card> result = new List<YGOSharp.Card>();
if (side)
{
List<YGOSharp.Card> result = new List<YGOSharp.Card>();
foreach (var item in Program.I().ocgcore.sideReference)
{
result.Add(YGOSharp.CardsManager.Get(item.Value));
......@@ -2318,6 +2319,7 @@ public class DeckManager : ServantWithCardDescription
}
else
{
print(result);
UIHelper.trySetLableText(
gameObjectSearch,
"title_",
......
......@@ -45,7 +45,7 @@ BoxCollider:
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Size: {x: 210, y: 480, z: 0}
m_Size: {x: 210, y: 422, z: 0}
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &11489760
MonoBehaviour:
......@@ -2993,7 +2993,7 @@ MonoBehaviour:
keepCrispWhenShrunk: 1
mTrueTypeFont: {fileID: 12800000, guid: f775853fdfd14bb47934543e95c3bae3, type: 3}
mFont: {fileID: 0}
mText: "\u8D85\u5148\u884C\u5361"
mText: "\u8D44\u6E90\u4E0B\u8F7D"
mFontSize: 30
mFontStyle: 0
mAlignment: 1
......
......@@ -4,7 +4,7 @@
"com.unity.2d.tilemap": "1.0.0",
"com.unity.analytics": "3.6.12",
"com.unity.burst": "1.8.18",
"com.unity.ide.vscode": "1.2.5",
"com.unity.ide.visualstudio": "2.0.23",
"com.unity.postprocessing": "3.4.0",
"com.unity.test-framework": "1.1.33",
"com.unity.timeline": "1.6.5",
......
......@@ -38,11 +38,13 @@
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.vscode": {
"version": "1.2.5",
"com.unity.ide.visualstudio": {
"version": "2.0.23",
"depth": 0,
"source": "registry",
"dependencies": {},
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
"url": "https://packages.unity.com"
},
"com.unity.mathematics": {
......
......@@ -19,7 +19,7 @@ MonoBehaviour:
width: 1512
height: 916
m_ShowMode: 4
m_Title: Hierarchy
m_Title: Simulator
m_RootView: {fileID: 2}
m_MinSize: {x: 875, y: 300}
m_MaxSize: {x: 10000, y: 10000}
......@@ -119,7 +119,7 @@ MonoBehaviour:
m_MinSize: {x: 300, y: 200}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
controlID: 53
controlID: 73
--- !u!114 &6
MonoBehaviour:
m_ObjectHideFlags: 52
......@@ -144,7 +144,7 @@ MonoBehaviour:
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 16192, y: 16192}
vertical: 1
controlID: 54
controlID: 74
--- !u!114 &7
MonoBehaviour:
m_ObjectHideFlags: 52
......@@ -165,11 +165,11 @@ MonoBehaviour:
x: 0
y: 0
width: 1147
height: 391
height: 462
m_MinSize: {x: 200, y: 100}
m_MaxSize: {x: 16192, y: 8096}
vertical: 0
controlID: 17
controlID: 75
--- !u!114 &8
MonoBehaviour:
m_ObjectHideFlags: 52
......@@ -188,7 +188,7 @@ MonoBehaviour:
x: 0
y: 0
width: 282.5
height: 391
height: 462
m_MinSize: {x: 201, y: 221}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 13}
......@@ -214,7 +214,7 @@ MonoBehaviour:
x: 282.5
y: 0
width: 864.5
height: 391
height: 462
m_MinSize: {x: 202, y: 221}
m_MaxSize: {x: 4002, y: 4021}
m_ActualView: {fileID: 14}
......@@ -239,9 +239,9 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 391
y: 462
width: 1147
height: 475
height: 404
m_MinSize: {x: 231, y: 271}
m_MaxSize: {x: 10001, y: 10021}
m_ActualView: {fileID: 15}
......@@ -269,8 +269,8 @@ MonoBehaviour:
y: 0
width: 365
height: 866
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_MinSize: {x: 276, y: 71}
m_MaxSize: {x: 4001, y: 4021}
m_ActualView: {fileID: 17}
m_Panes:
- {fileID: 17}
......@@ -560,7 +560,7 @@ MonoBehaviour:
m_Position:
m_Target: {x: -0.9613698, y: 0.29541966, z: -0.011044071}
speed: 2
m_Value: {x: 74.80919, y: 7.592579, z: -0.95798886}
m_Value: {x: -0.9613698, y: 0.29541966, z: -0.011044071}
m_RenderMode: 0
m_CameraMode:
drawMode: 0
......@@ -613,7 +613,7 @@ MonoBehaviour:
m_Size:
m_Target: 1.3784163
speed: 2
m_Value: 308.5191
m_Value: 1.3784163
m_Ortho:
m_Target: 1
speed: 2
......@@ -662,7 +662,7 @@ MonoBehaviour:
x: 0
y: 96
width: 281.5
height: 370
height: 441
m_ViewDataDictionary: {fileID: 0}
m_OverlayCanvas:
m_LastAppliedPresetName: Default
......@@ -673,7 +673,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: 2c87dfff7e87dfff548bdfff0468e2ffa87ee2ffba7ee2ffde7ee2ff3c80e2ff8e80e2ff5a84e2ff4685eaff7485eaff4e9ceaffdcf7ecffb60eedff2446effffe5cefff7474f2ffe274f2ffe674f2ffb2a1f2ffd6a1f2ff804cf4ffee4cf4fff24cf4ffe279f4ff460df5ffb40df5ffb80df5ffa83af5ff3c2bf6ffaa2bf6ffae2bf6ffc441f6ff7a58f6ff8c58f6ff9e58f6ffce5bf6ffd25bf6ff2c5ff6ff4c5ff6ff9a5ff6ff9e5ff6ff9c60f6ffe002f7fff202f7ff0003f7ff0c03f7ff1a03f7ff4e03f7ff5203f7ff6819f7ff4230f7fff09cf8fff49cf8ffe4c9f8ffb669f9ff246af9ff286af9ff0697f9ff1897f9ff1637faff1a37faff0a64fafffa2bfbfffe2bfbffee58fbff8af7fbff9cf7fbffaaf7fbffb6f7fbffc4f7fbfff8f7fbfffcf7fbffc824fcffec24fcff96e9fcffb0e9fcffe4e9fcffe8e9fcffa216fdffb416fdffc616fdffd816fdffcce5fdfff0e5fdfff4e5fdffe412feff0a95ffff0e95fffffec1ffff06fbffff
m_ExpandedIDs: a862e3fffa62e3ffd066e3ff7470e6ffc670e6ff9c74e6ff8e96e7ffe296e7ffba9ae7ff06fbffff
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -721,7 +721,7 @@ MonoBehaviour:
x: 282.5
y: 96
width: 862.5
height: 370
height: 441
m_ViewDataDictionary: {fileID: 0}
m_OverlayCanvas:
m_LastAppliedPresetName: Default
......@@ -751,10 +751,10 @@ MonoBehaviour:
- UnityEditor.DeviceSimulation.ApplicationSettingsPlugin
pluginStates:
- '{}'
scale: 24
scale: 21
fitToScreenEnabled: 0
rotationDegree: 270
highlightSafeAreaEnabled: 1
highlightSafeAreaEnabled: 0
friendlyName: Apple iPhone 13 Pro Max
networkReachability: 1
systemLanguage: 10
......@@ -780,9 +780,9 @@ MonoBehaviour:
m_Pos:
serializedVersion: 2
x: 0
y: 487
y: 558
width: 1146
height: 454
height: 383
m_ViewDataDictionary: {fileID: 0}
m_OverlayCanvas:
m_LastAppliedPresetName: Default
......@@ -813,9 +813,9 @@ MonoBehaviour:
m_IsLocked: 0
m_FolderTreeState:
scrollPos: {x: 0, y: 179}
m_SelectedIDs: daae0000
m_LastClickedID: 44762
m_ExpandedIDs: 0000000078ae00007aae00007cae00007eae000080ae000082ae000084ae00008cae000000ca9a3bffffff7f
m_SelectedIDs: 0aaf0000
m_LastClickedID: 44810
m_ExpandedIDs: 00000000aaae0000acae0000aeae0000b0ae0000b2ae0000b4ae0000b6ae0000bcae000000ca9a3bffffff7f
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -843,7 +843,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: 0000000078ae00007aae00007cae00007eae000080ae000082ae000084ae0000
m_ExpandedIDs: 00000000aaae0000acae0000aeae0000b0ae0000b2ae0000b4ae0000b6ae0000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......
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