Skip to content

Commit 7b270a5

Browse files
authored
Merge pull request #44 from MuNET-OSS/feat/mumod-integration
Feat/mumod-integration
2 parents d358cfd + f7b94a4 commit 7b270a5

28 files changed

Lines changed: 966 additions & 225 deletions

MaiChartManager.GenClient/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
var psi = new ProcessStartInfo
5454
{
5555
FileName = "cmd.exe",
56-
Arguments = "/c pnpm exec ts-node genClient.ts",
56+
Arguments = "/c pnpm exec tsx genClient.ts",
5757
WorkingDirectory = frontDir,
5858
UseShellExecute = false,
5959
};

MaiChartManager/Browser.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ private void webView21_CoreWebView2InitializationCompleted(object sender, CoreWe
8989
webView21.CoreWebView2.PermissionRequested += WebViewHelper.OnPermissionRequested;
9090
webView21.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
9191
webView21.CoreWebView2.WebMessageReceived += OnWebMessageReceived;
92+
93+
#if DEBUG
94+
WindowState = FormWindowState.Minimized;
95+
#endif
9296
}
9397

9498
private async void CoreWebView2_NewWindowRequested(object? sender, CoreWebView2NewWindowRequestedEventArgs e)

MaiChartManager/Controllers/App/OobeController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ public IActionResult DeleteGamePathHistory([FromBody] string path)
6969
}
7070

7171
[HttpPost]
72-
public void InitializeGameData()
72+
public async Task InitializeGameData()
7373
{
74-
settings.InitializeGameData();
74+
await settings.InitializeGameData();
7575
}
7676

7777
[HttpGet]

MaiChartManager/Controllers/AssetDir/AssetDirController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void PutAssetDirTxtValue([FromBody] PutAssetDirTxtValueRequest req)
103103
}
104104

105105
[HttpPost]
106-
public void RequestLocalImportDir()
106+
public async Task RequestLocalImportDir()
107107
{
108108
var dialog = new FolderBrowserDialog
109109
{
@@ -133,7 +133,7 @@ public void RequestLocalImportDir()
133133
var dest = Path.Combine(StaticSettings.StreamingAssets, destName);
134134
logger.LogInformation("Src: {src} Dest: {dest}", src, dest);
135135
FileSystem.CopyDirectory(src, dest, UIOption.AllDialogs);
136-
settings.RescanAll();
136+
await settings.RescanAll();
137137
}
138138

139139
public record UploadAssetDirResult(string DirName);
@@ -181,7 +181,7 @@ public async Task<UploadAssetDirResult> UploadAssetDir(string? destName)
181181
section = await reader.ReadNextSectionAsync();
182182
}
183183

184-
settings.RescanAll();
184+
await settings.RescanAll();
185185

186186
return new UploadAssetDirResult(destName);
187187
}

MaiChartManager/Controllers/AssetDir/MusicListController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public IEnumerable<MusicXmlWithABJacket> GetMusicList()
1414
}
1515

1616
[HttpPost]
17-
public void ReloadAll()
17+
public async Task ReloadAll()
1818
{
19-
settings.RescanAll();
19+
await settings.RescanAll();
2020
}
2121
}

MaiChartManager/Controllers/Mod/ConfigurationController.cs

Lines changed: 17 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,91 +12,25 @@ namespace MaiChartManager.Controllers.Mod;
1212

1313
[ApiController]
1414
[Route("MaiChartManagerServlet/[action]Api")]
15-
public class ConfigurationController(StaticSettings settings, ILogger<ConfigurationController> logger) : ControllerBase
15+
public class ConfigurationController : ControllerBase
1616
{
17-
public class UnsupportedConfigApiVersionException() : Exception(Locale.UnsupportedConfigVersion);
17+
private readonly StaticSettings settings;
18+
private readonly ILogger<ConfigurationController> logger;
19+
private readonly ModConfigService modConfigService;
1820

19-
public class ConfigCorruptedException() : Exception(Locale.AquaMaiConfigCorrupted);
20-
21-
public class AquaMaiNotInstalledException() : Exception(Locale.AquaMaiNotInstalled);
22-
23-
public class AquaMaiSignatureVerificationFailedException() : Exception("AquaMaiSignatureVerificationFailed");
24-
25-
[NonAction]
26-
private static void CheckConfigApiVersion(HeadlessConfigInterface configInterface)
27-
{
28-
var currentSupportedApiVersion = new Version(1, 1);
29-
var configApiVersion = new Version(configInterface.ApiVersion);
30-
if (currentSupportedApiVersion.Major != configApiVersion.Major)
31-
{
32-
throw new UnsupportedConfigApiVersionException();
33-
}
34-
35-
if (currentSupportedApiVersion.Minor > configApiVersion.Minor)
36-
{
37-
throw new UnsupportedConfigApiVersionException();
38-
}
39-
}
40-
41-
[NonAction]
42-
public static IConfig GetCurrentAquaMaiConfig(bool forceDefault = false, bool skipSignatureCheck = false)
21+
public ConfigurationController(StaticSettings settings, ILogger<ConfigurationController> logger, ModConfigService modConfigService)
4322
{
44-
if (!System.IO.File.Exists(ModPaths.AquaMaiDllInstalledPath))
45-
{
46-
throw new AquaMaiNotInstalledException();
47-
}
48-
49-
var binary = System.IO.File.ReadAllBytes(ModPaths.AquaMaiDllInstalledPath);
50-
if (!skipSignatureCheck)
51-
{
52-
var sigResult = AquaMaiSignatureV2.VerifySignature(binary);
53-
if (sigResult.Status != AquaMaiSignatureV2.VerifyStatus.Valid)
54-
{
55-
throw new AquaMaiSignatureVerificationFailedException();
56-
}
57-
}
58-
var configInterface = HeadlessConfigLoader.LoadFromPacked(binary);
59-
var config = configInterface.CreateConfig();
60-
CheckConfigApiVersion(configInterface);
61-
if (System.IO.File.Exists(ModPaths.AquaMaiConfigPath) && !forceDefault)
62-
{
63-
try
64-
{
65-
var view = configInterface.CreateConfigView(System.IO.File.ReadAllText(ModPaths.AquaMaiConfigPath));
66-
var migrationManager = configInterface.GetConfigMigrationManager();
67-
68-
if (migrationManager.GetVersion(view) != migrationManager.LatestVersion)
69-
{
70-
Console.WriteLine("Migrating AquaMai config from {0} to {1}", migrationManager.GetVersion(view), migrationManager.LatestVersion);
71-
view = migrationManager.Migrate(view);
72-
}
73-
74-
var parser = configInterface.GetConfigParser();
75-
parser.Parse(config, view);
76-
StaticSettings.UpdateAssetPathsFromAquaMaiConfig(config);
77-
}
78-
catch (Exception ex)
79-
{
80-
Console.WriteLine("无法加载 AquaMai 配置");
81-
Console.WriteLine(ex);
82-
if (ex.Message.Contains("Could not migrate the config"))
83-
{
84-
// 这个应该是,AquaMai 未安装或需要更新
85-
throw;
86-
}
87-
// 这个的提示是 AquaMai 配置文件损坏
88-
throw new ConfigCorruptedException();
89-
}
90-
}
91-
92-
return config;
23+
this.settings = settings;
24+
this.logger = logger;
25+
this.modConfigService = modConfigService;
9326
}
9427

9528
[HttpGet]
96-
public AquaMaiConfigDto.ConfigDto GetAquaMaiConfig(bool forceDefault = false, bool skipSignatureCheck = false)
29+
public async Task<AquaMaiConfigDto.ConfigDto> GetAquaMaiConfig(bool forceDefault = false, bool skipSignatureCheck = false)
9730
{
31+
var dllPath = await modConfigService.GetAquaMaiDllPath();
9832
Dictionary<string, string[]>? configSort = null;
99-
using (var stream = new FileStream(ModPaths.AquaMaiDllInstalledPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
33+
using (var stream = new FileStream(dllPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
10034
{
10135
var asm = ModuleDefinition.ReadModule(stream);
10236
var configSortRes = asm.Resources.FirstOrDefault(it => it is EmbeddedResource { Name: "configSort.yaml.compressed" } or EmbeddedResource { Name: "configSort.yaml" });
@@ -108,7 +42,8 @@ public AquaMaiConfigDto.ConfigDto GetAquaMaiConfig(bool forceDefault = false, bo
10842
configSort = deserializer.Deserialize<Dictionary<string, string[]>>(yaml);
10943
}
11044
}
111-
var config = GetCurrentAquaMaiConfig(forceDefault, skipSignatureCheck);
45+
var shouldSkipSignatureCheck = skipSignatureCheck || !string.Equals(dllPath, ModPaths.AquaMaiDllInstalledPath, StringComparison.OrdinalIgnoreCase);
46+
var config = await modConfigService.GetCurrentAquaMaiConfig(forceDefault, shouldSkipSignatureCheck);
11247
return new AquaMaiConfigDto.ConfigDto(
11348
config.ReflectionManager.Sections.Select(section =>
11449
{
@@ -124,11 +59,12 @@ public AquaMaiConfigDto.ConfigDto GetAquaMaiConfig(bool forceDefault = false, bo
12459
[HttpPut]
12560
public async Task SetAquaMaiConfig(AquaMaiConfigDto.ConfigSaveDto config)
12661
{
62+
var dllPath = await modConfigService.GetAquaMaiDllPath();
12763
var jsonOptions = new JsonSerializerOptions();
12864
jsonOptions.Converters.Add(new JsonStringEnumConverter());
12965

130-
var configInterface = HeadlessConfigLoader.LoadFromPacked(ModPaths.AquaMaiDllInstalledPath);
131-
CheckConfigApiVersion(configInterface);
66+
var configInterface = HeadlessConfigLoader.LoadFromPacked(dllPath);
67+
modConfigService.CheckConfigApiVersion(configInterface);
13268
var configEdit = configInterface.CreateConfig();
13369

13470
foreach (var section in configEdit.ReflectionManager.Sections)
@@ -183,4 +119,4 @@ public async Task SetAquaMaiConfig(AquaMaiConfigDto.ConfigSaveDto config)
183119
// 可能修改了歌曲封面目录
184120
settings.ScanMusicList();
185121
}
186-
}
122+
}

MaiChartManager/Controllers/Mod/InstallationController.cs

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace MaiChartManager.Controllers.Mod;
99

1010
[ApiController]
1111
[Route("MaiChartManagerServlet/[action]Api")]
12-
public class InstallationController(StaticSettings settings, ILogger<InstallationController> logger) : ControllerBase
12+
public class InstallationController(StaticSettings settings, ILogger<InstallationController> logger, MuModService muModService) : ControllerBase
1313
{
1414
private static string judgeDisplay4BPath = Path.Combine(StaticSettings.exeDir, "Resources", "JudgeDisplay4B");
1515

@@ -35,7 +35,12 @@ public record GameModInfo(
3535
bool IsHidConflictExist,
3636
AquaMaiSignatureV2.VerifyResult? Signature,
3737
bool IsAdxHidIoModAbsent,
38-
bool IsMmlLegacyLibsInstalled
38+
bool IsMmlLegacyLibsInstalled,
39+
bool MuModInstalled,
40+
string? MuModVersion,
41+
string? MuModChannel,
42+
string? MuModCacheVersion,
43+
bool IsBothModsPresent
3944
);
4045

4146
[HttpGet]
@@ -50,11 +55,25 @@ public GameModInfo GetGameModInfo()
5055

5156
var aquaMaiBuiltinVersion = FileVersionInfo.GetVersionInfo(ModPaths.AquaMaiDllBuiltinPath).ProductVersion;
5257

58+
var muModInstalled = muModService.IsMuModInstalled();
59+
5360
AquaMaiSignatureV2.VerifyResult? sig = null;
5461
if (aquaMaiInstalled)
5562
{
5663
sig = AquaMaiSignatureV2.VerifySignature(System.IO.File.ReadAllBytes(ModPaths.AquaMaiDllInstalledPath));
5764
}
65+
else if (muModInstalled)
66+
{
67+
sig = AquaMaiSignatureV2.VerifySignature(System.IO.File.ReadAllBytes(ModPaths.MuModDllInstalledPath));
68+
}
69+
var muModVersion = muModInstalled ? muModService.GetMuModVersion() : null;
70+
string? muModChannel = null;
71+
string? muModCacheVersion = null;
72+
if (muModInstalled)
73+
{
74+
try { muModChannel = muModService.ReadConfig().Channel; } catch { }
75+
muModCacheVersion = muModService.GetCacheInfo();
76+
}
5877

5978
return new GameModInfo(
6079
IsMelonInstalled(),
@@ -65,7 +84,12 @@ public GameModInfo GetGameModInfo()
6584
GetIsHidConflictExist(),
6685
sig,
6786
GetIsAdxHidIoModAbsent(),
68-
GetIsMmlLegacyLibsInstalled()
87+
GetIsMmlLegacyLibsInstalled(),
88+
muModInstalled,
89+
muModVersion,
90+
muModChannel,
91+
muModCacheVersion,
92+
aquaMaiInstalled && muModInstalled
6993
);
7094
}
7195

@@ -198,6 +222,10 @@ public void InstallAquaMai()
198222
var src = Path.Combine(StaticSettings.exeDir, "AquaMai.dll");
199223
var dest = Path.Combine(StaticSettings.GamePath, @"Mods\AquaMai.dll");
200224
CopyFile(src, dest);
225+
if (System.IO.File.Exists(ModPaths.MuModDllInstalledPath))
226+
{
227+
System.IO.File.Delete(ModPaths.MuModDllInstalledPath);
228+
}
201229
}
202230

203231
[HttpPost]
@@ -265,11 +293,58 @@ public async Task InstallAquaMaiOnline(InstallAquaMaiOnlineDto req)
265293
var dest = Path.Combine(StaticSettings.GamePath, @"Mods\AquaMai.dll");
266294
Directory.CreateDirectory(Path.GetDirectoryName(dest));
267295
await System.IO.File.WriteAllBytesAsync(dest, data);
296+
if (System.IO.File.Exists(ModPaths.MuModDllInstalledPath))
297+
{
298+
System.IO.File.Delete(ModPaths.MuModDllInstalledPath);
299+
}
268300
return;
269301
}
270302
throw new InvalidOperationException("Failed to download AquaMai from all urls", lastException);
271303
}
272304

305+
[HttpPost]
306+
public async Task InstallMuMod()
307+
{
308+
CopyFile(ModPaths.MuModDllBuiltinPath, ModPaths.MuModDllInstalledPath);
309+
310+
if (System.IO.File.Exists(ModPaths.AquaMaiDllInstalledPath))
311+
{
312+
System.IO.File.Delete(ModPaths.AquaMaiDllInstalledPath);
313+
}
314+
315+
if (!System.IO.File.Exists(ModPaths.MuModConfigPath))
316+
{
317+
System.IO.File.WriteAllText(ModPaths.MuModConfigPath, "Channel = \"slow\"\nCachePath = \"LocalAssets\\\\MuMod.cache\"\n");
318+
}
319+
320+
try
321+
{
322+
await muModService.EnsureCache(CancellationToken.None);
323+
}
324+
catch (Exception e)
325+
{
326+
logger.LogError(e, "Failed to download MuMod cache during install, but DLL was installed successfully");
327+
}
328+
}
329+
330+
[HttpPost]
331+
public void DeleteAquaMai()
332+
{
333+
if (System.IO.File.Exists(ModPaths.AquaMaiDllInstalledPath))
334+
{
335+
FileSystem.DeleteFile(ModPaths.AquaMaiDllInstalledPath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
336+
}
337+
}
338+
339+
[HttpPost]
340+
public void DeleteMuMod()
341+
{
342+
if (System.IO.File.Exists(ModPaths.MuModDllInstalledPath))
343+
{
344+
FileSystem.DeleteFile(ModPaths.MuModDllInstalledPath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
345+
}
346+
}
347+
273348
[HttpPost]
274349
public void KillGameProcess()
275350
{

0 commit comments

Comments
 (0)