diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs index 648bbd62..e39ca58e 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs @@ -18,11 +18,13 @@ public class AxiNS public AxiNSUser user; public AxiNSMount mount; public AxiNSIO io; + public AxiNSWaitHandle wait; AxiNS() { user = new AxiNSUser(); mount = new AxiNSMount(); io = new AxiNSIO(); + wait = new AxiNSWaitHandle(); } /// diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs index 7e20444b..9e3fe02e 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs @@ -1,86 +1,97 @@ #if UNITY_SWITCH using nn.fs; -using System.Security.Cryptography; - #endif public class AxiNSIO { - string save_name => AxiNS.instance.mount.SaveMountName; - public string save_path => $"{save_name}:/"; + string save_name => AxiNS.instance.mount.SaveMountName; + public string save_path => $"{save_name}:/"; #if UNITY_SWITCH private FileHandle fileHandle = new nn.fs.FileHandle(); #endif - /// - /// 检查Path是否存在 - /// - /// - /// - public bool CheckPathExists(string filePath) - { + /// + /// 检查Path是否存在 + /// + /// + /// + public bool CheckPathExists(string filePath) + { #if !UNITY_SWITCH return false; #else - nn.fs.EntryType entryType = 0; + nn.fs.EntryType entryType = 0; nn.Result result = nn.fs.FileSystem.GetEntryType(ref entryType, filePath); //result.abortUnlessSuccess(); //这个异常捕获。真的别扭 return nn.fs.FileSystem.ResultPathAlreadyExists.Includes(result); #endif - } - /// - /// 检查Path是否不存在 - /// - /// - /// - public bool CheckPathNotFound(string filePath) - { + } + /// + /// 检查Path是否不存在 + /// + /// + /// + public bool CheckPathNotFound(string filePath) + { #if !UNITY_SWITCH return false; #else - nn.fs.EntryType entryType = 0; + nn.fs.EntryType entryType = 0; nn.Result result = nn.fs.FileSystem.GetEntryType(ref entryType, filePath); //这个异常捕获。真的别扭 return nn.fs.FileSystem.ResultPathNotFound.Includes(result); #endif - } - /// - /// 创建目录,目录存在也会返回true - /// - /// - /// - public bool CreateDir(string filePath) - { + } + /// + /// 创建目录,目录存在也会返回true + /// + /// + /// + public bool CreateDir(string filePath) + { #if !UNITY_SWITCH return false; #else - // 使用封装函数检查和创建父目录 - if (!EnsureParentDirectory(filePath, true)) - { - UnityEngine.Debug.LogError($"无法确保父目录,文件写入取消: {filePath}"); - return false; - } + // 使用封装函数检查和创建父目录 + if (!EnsureParentDirectory(filePath, true)) + { + UnityEngine.Debug.LogError($"无法确保父目录,文件写入取消: {filePath}"); + return false; + } return true; #endif - } - /// - /// 保存并创建文件(如果目录不存在回先自动创建目录) - /// - /// - /// - /// - public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms) - { - return FileToSaveWithCreate(filePath, ms.ToArray()); - } - /// - /// 保存并创建文件(如果目录不存在回先自动创建目录) - /// - /// - /// - /// - public bool FileToSaveWithCreate(string filePath, byte[] data) - { + } + + /// + /// 保存并创建文件(如果目录不存在回先自动创建目录) + /// + /// + /// + /// + public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms) + { + return FileToSaveWithCreate(filePath, ms.ToArray()); + } + /// + /// 保存并创建文件(如果目录不存在回先自动创建目录) + /// + /// + /// + /// + public AxiNSWait_FileToSaveByMSWithCreate FileToSaveWithCreateAsync(string filePath, System.IO.MemoryStream ms) + { + var wait = new AxiNSWait_FileToSaveByMSWithCreate(filePath, ms); + AxiNS.instance.wait.AddWait(wait); + return wait; + } + /// + /// 保存并创建文件(如果目录不存在回先自动创建目录) + /// + /// + /// + /// + public bool FileToSaveWithCreate(string filePath, byte[] data) + { #if !UNITY_SWITCH return false; #else @@ -184,21 +195,33 @@ public class AxiNSIO return true; #endif - } - public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms) - { - if (LoadSwitchDataFile(filename, out byte[] outputData)) - { - using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms)) - { - writer.Write(outputData); - } - return true; - } - return false; - } - public bool LoadSwitchDataFile(string filename, out byte[] outputData) - { + } + /// + /// 保存并创建文件(如果目录不存在回先自动创建目录) + /// + /// + /// + /// + public AxiNSWait_FileToSaveWithCreate FileToSaveWithCreateAsync(string filePath, byte[] data) + { + var wait = new AxiNSWait_FileToSaveWithCreate(filePath, data); + AxiNS.instance.wait.AddWait(wait); + return wait; + } + public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms) + { + if (LoadSwitchDataFile(filename, out byte[] outputData)) + { + using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms)) + { + writer.Write(outputData); + } + return true; + } + return false; + } + public bool LoadSwitchDataFile(string filename, out byte[] outputData) + { #if !UNITY_SWITCH outputData = null; return false; @@ -249,9 +272,15 @@ public class AxiNSIO outputData = loadedData; return true; #endif - } - public bool DeletePathFile(string filename) - { + } + public AxiNSWait_LoadSwitchDataFile LoadSwitchDataFileAsync(string filename) + { + var wait = new AxiNSWait_LoadSwitchDataFile(filename); + AxiNS.instance.wait.AddWait(wait); + return wait; + } + public bool DeletePathFile(string filename) + { #if !UNITY_SWITCH return false; #else @@ -270,7 +299,7 @@ public class AxiNSIO if (result.IsSuccess() == false) { UnityEngine.Debug.LogError($"nn.fs.File.Delete 失败 {filename} : result=>{result.GetErrorInfo()}"); - return false; + return false; } result = nn.fs.FileSystem.Commit(save_name); if (!result.IsSuccess()) @@ -287,8 +316,14 @@ public class AxiNSIO #endif } + public AxiNSWait_DeletePathFile DeletePathFileAsync(string filename) + { + var wait = new AxiNSWait_DeletePathFile(filename); + AxiNS.instance.wait.AddWait(wait); + return wait; + } public bool DeletePathDir(string filename) - { + { #if !UNITY_SWITCH return false; #else @@ -322,6 +357,12 @@ public class AxiNSIO #endif #endif } + public AxiNSWait_DeletePathDir DeletePathDirAsync(string filename) + { + var wait = new AxiNSWait_DeletePathDir(filename); + AxiNS.instance.wait.AddWait(wait); + return wait; + } /// /// 递归删除目录 @@ -405,8 +446,7 @@ public class AxiNSIO #endif } - - public bool RenameDir(string oldpath,string newpath) + public bool RenameDir(string oldpath, string newpath) { #if !UNITY_SWITCH return false; @@ -443,7 +483,7 @@ public class AxiNSIO #endif } bool EnsureParentDirectory(string filePath, bool bAutoCreateDir = true) - { + { #if !UNITY_SWITCH return false; #else @@ -517,16 +557,16 @@ public class AxiNSIO // 路径存在且是目录 UnityEngine.Debug.Log($"父目录 {fullDirectoryPath} 已存在且有效"); return true; - + #endif - } - /// - /// 检查指定挂载点是否可访问 - /// - /// 路径前缀,例如 "save:/" 或 "sd:/" - /// 挂载点是否可访问 - bool IsMountPointAccessible(string pathPrefix) - { + } + /// + /// 检查指定挂载点是否可访问 + /// + /// 路径前缀,例如 "save:/" 或 "sd:/" + /// 挂载点是否可访问 + bool IsMountPointAccessible(string pathPrefix) + { #if !UNITY_SWITCH return false; #else @@ -564,5 +604,5 @@ public class AxiNSIO return true; // 其他挂载点需根据实际需求实现 } #endif - } + } } diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs index a634a432..8b32a30b 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs @@ -1,5 +1,6 @@ #if UNITY_SWITCH using nn.account; +using static AxiHttp; #endif public class AxiNSMount { diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta new file mode 100644 index 00000000..99d60f26 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e28ed9d2fb16c7f42b28cafb6a2ce0ac +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs new file mode 100644 index 00000000..009b93e8 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs @@ -0,0 +1,119 @@ +public abstract class AxiNSWaitBase : UnityEngine.CustomYieldInstruction +{ + protected bool IsDone; + public abstract void Invoke(); + public string errmsg = string.Empty; + public AxiNSWaitBase() + { + this.IsDone = false; + } + + public void SetDone() + { + this.IsDone = true; + } + + ~AxiNSWaitBase() + { + } + + public override bool keepWaiting + { + get { return !IsDone; } + } +} + + + +public struct S_NSWAIT_PathWithBytes +{ + public string filePath; + public byte[] data; +} + +public class AxiNSWait_FileToSaveWithCreate : AxiNSWaitBase +{ + S_NSWAIT_PathWithBytes req; + public bool result; + public AxiNSWait_FileToSaveWithCreate(string filePath, byte[] data) + { + req = new S_NSWAIT_PathWithBytes() { filePath = filePath, data = data }; + } + + public override void Invoke() + { + result = AxiNS.instance.io.FileToSaveWithCreate(req.filePath, req.data); + } +} + +public struct S_NSWAIT_PathWithMS +{ + public string filePath; + public System.IO.MemoryStream ms; +} + +public class AxiNSWait_FileToSaveByMSWithCreate : AxiNSWaitBase +{ + S_NSWAIT_PathWithMS req; + public bool result; + public AxiNSWait_FileToSaveByMSWithCreate(string filePath, System.IO.MemoryStream ms) + { + req = new S_NSWAIT_PathWithMS() { filePath = filePath, ms = ms }; + } + + public override void Invoke() + { + result = AxiNS.instance.io.FileToSaveWithCreate(req.filePath, req.ms); + } +} + +public struct S_NSWAIT_Path +{ + public string filePath; +} + +public class AxiNSWait_LoadSwitchDataFile : AxiNSWaitBase +{ + S_NSWAIT_Path req; + public bool result; + public byte[] outputData; + public AxiNSWait_LoadSwitchDataFile(string filePath) + { + req = new S_NSWAIT_Path() { filePath = filePath}; + } + + public override void Invoke() + { + result = AxiNS.instance.io.LoadSwitchDataFile(req.filePath, out outputData); + } +} + +public class AxiNSWait_DeletePathFile : AxiNSWaitBase +{ + S_NSWAIT_Path req; + public bool result; + public AxiNSWait_DeletePathFile(string filePath) + { + req = new S_NSWAIT_Path() { filePath = filePath }; + } + + public override void Invoke() + { + result = AxiNS.instance.io.DeletePathFile(req.filePath); + } +} + +public class AxiNSWait_DeletePathDir : AxiNSWaitBase +{ + S_NSWAIT_Path req; + public bool result; + public AxiNSWait_DeletePathDir(string filePath) + { + req = new S_NSWAIT_Path() { filePath = filePath }; + } + + public override void Invoke() + { + result = AxiNS.instance.io.DeletePathDir(req.filePath); + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta new file mode 100644 index 00000000..ff72499f --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46a1a776d2f9dba49b9641d8e0976861 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs new file mode 100644 index 00000000..a8ba35f0 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +public class AxiNSWaitHandle +{ + static AutoResetEvent autoEvent = new AutoResetEvent(false); + static Thread waitThread = new Thread(Loop); + static bool bSingleInit = false; + static Queue m_QueueReady = new Queue(); + static Queue m_QueueWork = new Queue(); + public void AddWait(AxiNSWaitBase wait) + { + InitInternalThread(); + lock (m_QueueReady) + { + m_QueueReady.Enqueue(wait); + } + autoEvent.Set(); + } + + static void InitInternalThread() + { + if (bSingleInit) return; + waitThread.Start(); + bSingleInit = true; + } + + static void Loop() + { + while (autoEvent.WaitOne()) + { + lock (m_QueueReady) + { + while (m_QueueReady.Count > 0) + { + m_QueueWork.Enqueue(m_QueueReady.Dequeue()); + } + } + while (m_QueueWork.Count > 0) + { + AxiNSWaitBase wait = m_QueueWork.Dequeue(); + try + { + wait.Invoke(); + } + catch (Exception ex) + { + wait.errmsg = ex.ToString(); + UnityEngine.Debug.Log(ex.ToString()); + } + wait.SetDone(); + } + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta new file mode 100644 index 00000000..46fa015c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e36180ba1c4a8f4db3ceed533a43999 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: