From 206715b4828bf84758f4fc9281ea53cdeda48fff Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Thu, 23 Jan 2025 16:14:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E9=87=8D=E6=9E=84=E5=88=B0=E5=8D=95=E7=8B=AC=E7=9A=84?= =?UTF-8?q?FileDownloader=E7=B1=BB=E4=B8=AD,=E4=BB=A5=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E5=A4=9A=E4=B8=AARom=E5=90=8C=E6=97=B6=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E7=9A=84=E5=86=B2=E7=AA=81(=E4=BE=8B=E5=A6=82=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=85=B3=E7=B3=BB=E7=9A=84Rom)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Script/AppMain/App.cs | 4 +- .../AppMain/Manager/RomLib/FileDownloader.cs | 62 +++++++++ .../Manager/RomLib/FileDownloader.cs.meta | 2 + .../Script/AppMain/Manager/RomLib/RomFile.cs | 122 +++++++++++------- .../Script/AppMain/Manager/RomLib/RomLib.cs | 48 +++---- .../Script/AppMain/UI/GamesUI/RomItem.cs | 6 +- 6 files changed, 173 insertions(+), 71 deletions(-) create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs create mode 100644 AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs index 1a7216f7..aea378c1 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs @@ -30,6 +30,7 @@ namespace AxibugEmuOnline.Client.ClientCore public static AppShare share; public static GamePadManager gamePadMgr; public static SaveSlotManager SavMgr; + public static FileDownloader FileDownloader; static bool bTest; static string mTestSrvIP; @@ -75,7 +76,7 @@ namespace AxibugEmuOnline.Client.ClientCore { PSP2Init(); } - + FileDownloader = new FileDownloader(); settings = new AppSettings(); network = new NetworkHelper(); login = new AppLogin(); @@ -225,6 +226,7 @@ namespace AxibugEmuOnline.Client.ClientCore { foreach (var romLib in s_romLibs.Values) romLib.ExecuteFetchRomInfo(); starRomLib.ExecuteFetchRomInfo(); + FileDownloader.Update(); gamePadMgr.Update(); } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs new file mode 100644 index 00000000..c1d9f822 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs @@ -0,0 +1,62 @@ +using AxibugEmuOnline.Client.ClientCore; +using System; +using System.Collections.Generic; +using System.Security.Policy; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class FileDownloader + { + Dictionary m_downloadingTasks = new Dictionary(); + Dictionary> m_completeCallback = new Dictionary>(); + public void BeginDownload(string url, Action callback) + { + if (m_downloadingTasks.TryGetValue(url, out var downloadProxy)) return; + + m_completeCallback[url] = callback; + var downloadRequest = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{url}"); + m_downloadingTasks[url] = downloadRequest; + } + + public float? GetDownloadProgress(string url) + { + m_downloadingTasks.TryGetValue(url, out var proxy); + if (proxy == null) return null; + + return Mathf.Clamp01(proxy.downloadHandler.DownLoadPr); + } + + HashSet temp = new HashSet(); + public void Update() + { + temp.Clear(); + + foreach (var item in m_downloadingTasks) + { + var url = item.Key; + var proxy = item.Value; + if (proxy.downloadHandler.isDone) + { + temp.Add(url); + } + } + + foreach (var url in temp) + { + var overTask = m_downloadingTasks[url]; + m_downloadingTasks.Remove(url); + + if (!overTask.downloadHandler.bHadErr) + { + m_completeCallback[url].Invoke(overTask.downloadHandler.data); + m_completeCallback.Remove(url); + } + else + { + Debug.LogError(overTask.downloadHandler.ErrInfo); + } + } + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs.meta new file mode 100644 index 00000000..bfa54bd5 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/FileDownloader.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 86823d6828e1cf24da330443483b060b \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs index a86a5329..96d3eb29 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs @@ -13,8 +13,6 @@ namespace AxibugEmuOnline.Client public class RomFile { private HttpAPI.Resp_RomInfo webData; - private bool hasLocalFile; - private AxiHttpProxy.SendDownLoadProxy downloadRequest; /// 依赖的Rom文件 private List dependencies = new List(); @@ -26,12 +24,32 @@ namespace AxibugEmuOnline.Client switch (Platform) { case RomPlatformType.Nes: return false; - case RomPlatformType.Cps1: return true; + case RomPlatformType.Igs: + case RomPlatformType.Cps1: + case RomPlatformType.Cps2: + case RomPlatformType.Neogeo: + return true; default: throw new NotImplementedException($"未实现的平台{Platform}"); } } } + bool m_hasLocalFile; + public bool HasLocalFile + { + get + { + if (!m_hasLocalFile) return false; + + foreach (var depRom in dependencies) + { + if (!depRom.HasLocalFile) return false; + } + + return true; + } + } + /// 指示该Rom文件的存放路径 public string LocalFilePath => $"{App.PersistentDataPath(Platform)}/RemoteRoms/{FileName}"; @@ -40,7 +58,7 @@ namespace AxibugEmuOnline.Client { get { - if (!hasLocalFile) return false; + if (!HasLocalFile) return false; foreach (var depRom in dependencies) { @@ -55,8 +73,10 @@ namespace AxibugEmuOnline.Client { get { - var selfDownloading = downloadRequest != null && !downloadRequest.downloadHandler.isDone; - if (selfDownloading) return true; + if (!InfoReady) return false; + + var progress = App.FileDownloader.GetDownloadProgress(webData.url); + if (progress.HasValue) return true; foreach (var depRom in dependencies) { @@ -73,15 +93,21 @@ namespace AxibugEmuOnline.Client { if (!IsDownloading) return 0; - float total = 0f; + float progress = 0f; - total += downloadRequest != null ? downloadRequest.downloadHandler.DownLoadPr : 0; - foreach (var depRom in dependencies) + if (HasLocalFile) progress = 1f; + else { - total += depRom.Progress; + var downloadProgress = App.FileDownloader.GetDownloadProgress(webData.url); + progress = downloadProgress.HasValue ? downloadProgress.Value : 0; } - return total; + foreach (var depRom in dependencies) + { + progress += depRom.Progress; + } + + return progress / (dependencies.Count + 1); } } @@ -139,17 +165,38 @@ namespace AxibugEmuOnline.Client Page = insidePage; } + public void CheckLocalFileState() + { + if (webData == null) m_hasLocalFile = false; + else + { + if (App.FileDownloader.GetDownloadProgress(webData.url) == null) + { + if (MultiFileRom) + m_hasLocalFile = Directory.Exists(LocalFilePath); + else + m_hasLocalFile = File.Exists(LocalFilePath); + } + } + + foreach (var depRom in dependencies) + depRom.CheckLocalFileState(); + } + public void BeginDownload() { if (RomReady) return; if (IsDownloading) return; //检查依赖Rom的下载情况 - - App.StartCoroutine(DownloadRemoteRom((bytes) => + foreach (var depRom in dependencies) + { + depRom.BeginDownload(); + } + App.FileDownloader.BeginDownload(webData.url, (bytes) => { HandleRomFilePostProcess(bytes); - })); + }); } private void HandleRomFilePostProcess(byte[] bytes) @@ -161,9 +208,11 @@ namespace AxibugEmuOnline.Client Dictionary unzipFiles = new Dictionary(); //多rom文件的平台,下载下来的数据直接解压放入文件夹内 var zip = new ZipInputStream(new MemoryStream(bytes)); + + List depth0Files = new List(); while (true) { - var currentEntry = zip.GetNextEntry(); + var currentEntry = zip.GetNextEntry(); if (currentEntry == null) break; if (currentEntry.IsDirectory) continue; @@ -180,10 +229,18 @@ namespace AxibugEmuOnline.Client unzipFiles[$"{LocalFilePath}/{currentEntry.Name}"] = output.ToArray(); } + string rootDirName = null; + //如果第一层目录只有一个文件并且是文件夹,则所有文件层级外提一层 + if (depth0Files.Count == 1 && depth0Files[0].Contains('.')) + { + rootDirName = depth0Files[0]; + } + foreach (var item in unzipFiles) { - var path = item.Key; + var path = rootDirName != null ? item.Key.Substring(0, rootDirName.Length + 1) : item.Key; var data = item.Value; + Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, data); } } @@ -193,10 +250,8 @@ namespace AxibugEmuOnline.Client Directory.CreateDirectory(directPath); File.WriteAllBytes(LocalFilePath, bytes); - hasLocalFile = true; - - Eventer.Instance.PostEvent(EEvent.OnRomFileDownloaded, ID); } + Eventer.Instance.PostEvent(EEvent.OnRomFileDownloaded, ID); OnDownloadOver?.Invoke(this); } @@ -238,39 +293,16 @@ namespace AxibugEmuOnline.Client throw new Exception("Not Valid Rom Data"); } - private IEnumerator DownloadRemoteRom(Action callback) - { - downloadRequest = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{webData.url}"); - - while (!downloadRequest.downloadHandler.isDone) - { - yield return null; - Debug.Log($"下载进度:{downloadRequest.downloadHandler.DownLoadPr} ->{downloadRequest.downloadHandler.loadedLenght}/{downloadRequest.downloadHandler.NeedloadedLenght}"); - } - AxiHttpProxy.ShowAxiHttpDebugInfo(downloadRequest.downloadHandler); - - var request = downloadRequest; - downloadRequest = null; - if (!request.downloadHandler.bHadErr) - callback(request.downloadHandler.data); - else - callback(null); - } - public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo) { webData = resp_RomInfo; FileName = MultiFileRom ? Path.GetFileNameWithoutExtension(webData.url) : Path.GetFileName(webData.url); FileName = System.Net.WebUtility.UrlDecode(FileName); - - if (MultiFileRom) - hasLocalFile = Directory.Exists(LocalFilePath); - else - hasLocalFile = File.Exists(LocalFilePath); //收集依赖Rom if (webData.parentRomIdsList != null) { + dependencies.Clear(); foreach (var romID in webData.parentRomIdsList) { var romFile = new RomFile(Index, Page); @@ -280,7 +312,9 @@ namespace AxibugEmuOnline.Client romFile.SetWebData(romInfo); })); } - } + } + + CheckLocalFileState(); App.StartCoroutine(WaitInfoReady()); } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs index c361faa0..8b6eae53 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs @@ -17,9 +17,9 @@ namespace AxibugEmuOnline.Client /// 请求指令 private HashSet FetchPageCmd = new HashSet(); - private RomFile[] nesRomFetchList; - private Dictionary nesRomFileIdMapper = new Dictionary(); - private Dictionary nesRomFileNameMapper = new Dictionary(); + private RomFile[] RomFetchList; + private Dictionary RomFileIdMapper = new Dictionary(); + private Dictionary RomFileNameMapper = new Dictionary(); private HttpAPI.GetRomListAPI m_romGetFunc; private HttpAPI.SearchRomListAPI m_romSearchFunc; private RomPlatformType m_platform; @@ -43,9 +43,9 @@ namespace AxibugEmuOnline.Client private void OnRomStarStateChanged(int romID, bool star) { - if (nesRomFetchList == null) return; + if (RomFetchList == null) return; - var targetRom = nesRomFetchList.FirstOrDefault(rom => rom.ID == romID); + var targetRom = RomFetchList.FirstOrDefault(rom => rom.ID == romID); if (targetRom == null) return; targetRom.Star = star; @@ -54,7 +54,7 @@ namespace AxibugEmuOnline.Client public RomFile GetRomFile(string romFileName) { RomFile romFile; - nesRomFileNameMapper.TryGetValue(romFileName, out romFile); + RomFileNameMapper.TryGetValue(romFileName, out romFile); return romFile; } @@ -83,22 +83,22 @@ namespace AxibugEmuOnline.Client m_romGetFunc((page, romList) => { FetchPageCmd.Clear(); - nesRomFileIdMapper.Clear(); - nesRomFileNameMapper.Clear(); + RomFileIdMapper.Clear(); + RomFileNameMapper.Clear(); if (romList != null) - nesRomFetchList = new RomFile[romList.resultAllCount]; + RomFetchList = new RomFile[romList.resultAllCount]; else - nesRomFetchList = new RomFile[0]; + RomFetchList = new RomFile[0]; - for (int i = 0; i < nesRomFetchList.Length; i++) + for (int i = 0; i < RomFetchList.Length; i++) { //以后考虑用对象池实例化RomFile - nesRomFetchList[i] = new RomFile(i, i / PAGE_SIZE); + RomFetchList[i] = new RomFile(i, i / PAGE_SIZE); } SaveRomInfoFromWeb(romList); - callback.Invoke(nesRomFetchList); + callback.Invoke(RomFetchList); }, m_platform, 0, PAGE_SIZE); } else @@ -106,22 +106,22 @@ namespace AxibugEmuOnline.Client m_romSearchFunc((page, romList) => { FetchPageCmd.Clear(); - nesRomFileIdMapper.Clear(); - nesRomFileNameMapper.Clear(); + RomFileIdMapper.Clear(); + RomFileNameMapper.Clear(); if (romList != null) - nesRomFetchList = new RomFile[romList.resultAllCount]; + RomFetchList = new RomFile[romList.resultAllCount]; else - nesRomFetchList = new RomFile[0]; + RomFetchList = new RomFile[0]; - for (int i = 0; i < nesRomFetchList.Length; i++) + for (int i = 0; i < RomFetchList.Length; i++) { //以后考虑用对象池实例化RomFile - nesRomFetchList[i] = new RomFile(i, i / PAGE_SIZE); + RomFetchList[i] = new RomFile(i, i / PAGE_SIZE); } SaveRomInfoFromWeb(romList); - callback.Invoke(nesRomFetchList); + callback.Invoke(RomFetchList); }, m_platform, searchKey, 0, PAGE_SIZE); } } @@ -170,11 +170,11 @@ namespace AxibugEmuOnline.Client for (int i = 0; i < resp.gameList.Count; i++) { var webData = resp.gameList[i]; - RomFile targetRomFile = nesRomFetchList[webData.orderid]; + RomFile targetRomFile = RomFetchList[webData.orderid]; targetRomFile.SetWebData(webData); - nesRomFileIdMapper[webData.id] = nesRomFetchList[webData.orderid]; - nesRomFileNameMapper[targetRomFile.FileName] = targetRomFile; + RomFileIdMapper[webData.id] = RomFetchList[webData.orderid]; + RomFileNameMapper[targetRomFile.FileName] = targetRomFile; } } @@ -185,7 +185,7 @@ namespace AxibugEmuOnline.Client public void AddRomFile(RomFile rom) { - nesRomFileNameMapper[rom.FileName] = rom; + RomFileNameMapper[rom.FileName] = rom; } } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs index 0b67dd58..d03342d8 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs @@ -54,9 +54,11 @@ namespace AxibugEmuOnline.Client private void OnRomDownloaded(int romID) { - if (m_romfile == null || m_romfile.ID != romID) return; + if (m_romfile == null) return; - DownloadComplete.Play(); + m_romfile.CheckLocalFileState(); + if (m_romfile.RomReady) + DownloadComplete.Play(); } public void SetData(object data)