using UnityEditor; using UnityEngine; using System.IO; using Ichni.RhythmGame.Beatmap; namespace Ichni.Editor { public class IchniProjectDecryptor : EditorWindow { [MenuItem("Tools/Ichni/Decrypt Exported Project")] public static void ShowWindow() { // 打开文件夹选择面板,让用户选择被加密(导出)的工程文件夹 string exportFolderPath = EditorUtility.OpenFolderPanel("Select Exported Project Folder", Application.streamingAssetsPath + "/Export", ""); if (string.IsNullOrEmpty(exportFolderPath)) return; string projectName = new DirectoryInfo(exportFolderPath).Name; // 选择要输出解密后的工程文件夹(默认为 Projects 文件夹下的同名文件夹) string saveFolderPath = EditorUtility.SaveFolderPanel("Select Output Directory for Decrypted Project", Application.streamingAssetsPath + "/Projects", projectName); if (string.IsNullOrEmpty(saveFolderPath)) return; // 确保输出文件夹存在 if (!Directory.Exists(saveFolderPath)) { Directory.CreateDirectory(saveFolderPath); } bool success = true; // 分别解密并转存四个主要配置/谱面文件 success &= DecryptAndSave("ProjectInformation", exportFolderPath + "/ProjectInfo.bytes", saveFolderPath + "/ProjectInfo.json"); success &= DecryptAndSave("SongInformation", exportFolderPath + "/SongInfo.bytes", saveFolderPath + "/SongInfo.json"); success &= DecryptAndSave("Beatmap", exportFolderPath + "/Beatmap.bytes", saveFolderPath + "/Beatmap.json"); success &= DecryptAndSave("CommandScripts", exportFolderPath + "/CommandScripts.bytes", saveFolderPath + "/CommandScripts.json"); if (success) { EditorUtility.DisplayDialog("Decryption Complete", $"Project '{projectName}' has been successfully decrypted and saved to:\n{saveFolderPath}", "OK"); } else { EditorUtility.DisplayDialog("Decryption Finished with Warnings", $"Project '{projectName}' decryption finished, but some files might be missing or failed to decode. Check Console for details.", "OK"); } // 刷新 AssetDatabase AssetDatabase.Refresh(); } private static bool DecryptAndSave(string key, string inputPath, string outputPath) { if (!File.Exists(inputPath)) { Debug.LogWarning($"[IchniDecryptor] Missing encrypted file, skipping: {inputPath}"); return true; // 允许部分文件缺失(例如可能没有CommandScripts) } try { // 使用导出的加密配置进行读取 T data = ES3.Load(key, inputPath, ProjectManager.ExportSettings); // 使用明文保存配置转存为 JSON ES3.Save(key, data, outputPath, ProjectManager.SaveSettings); Debug.Log($"[IchniDecryptor] Successfully decrypted: {Path.GetFileName(inputPath)} -> {Path.GetFileName(outputPath)}"); return true; } catch (System.Exception e) { Debug.LogError($"[IchniDecryptor] Failed to decrypt {Path.GetFileName(inputPath)}: {e.Message}\n{e.StackTrace}"); return false; } } } }