Skip to content

Commit c7ab808

Browse files
committed
feat(mod): 同步 AppleChu 配置(FpsDisplay/FrameLock)并支持 d3d9 proxy 安装与状态检测
1 parent 34b74ae commit c7ab808

5 files changed

Lines changed: 59 additions & 14 deletions

File tree

ChuChartManager/Controllers/ModController.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace ChuChartManager.Controllers;
1111
public class ModController : ControllerBase
1212
{
1313
public record ModInfo(string Name, string Version);
14-
public record ModStatus(bool LoaderInstalled, List<ModInfo> Mods);
14+
public record ModStatus(bool LoaderInstalled, bool ProxyInstalled, List<ModInfo> Mods);
1515
public record ModSectionConfig(bool Enabled, Dictionary<string, object?> Entries);
1616
public record ModConfigRequest(Dictionary<string, ModSectionConfig> Sections);
1717

@@ -20,10 +20,11 @@ public ActionResult<ModStatus> GetStatus()
2020
{
2121
var gamePath = StaticSettings.GamePath;
2222
if (string.IsNullOrEmpty(gamePath))
23-
return Ok(new ModStatus(false, []));
23+
return Ok(new ModStatus(false, false, []));
2424

2525
var binPath = Path.Combine(gamePath, "bin");
2626
var loaderInstalled = System.IO.File.Exists(Path.Combine(binPath, "version.dll"));
27+
var proxyInstalled = System.IO.File.Exists(Path.Combine(binPath, "d3d9.dll"));
2728
var modsPath = Path.Combine(binPath, "mods");
2829
var mods = Directory.Exists(modsPath)
2930
? Directory.GetFiles(modsPath, "*.dll", SearchOption.TopDirectoryOnly)
@@ -32,11 +33,12 @@ public ActionResult<ModStatus> GetStatus()
3233
.ToList()
3334
: [];
3435

35-
return Ok(new ModStatus(loaderInstalled, mods));
36+
return Ok(new ModStatus(loaderInstalled, proxyInstalled, mods));
3637
}
3738

3839
private const string LoaderRepo = "MuNET-OSS/ChuModLoader";
3940
private const string LoaderAsset = "version.dll";
41+
private const string ProxyAsset = "d3d9.dll";
4042
private const string AppleChuRepo = "MuNET-OSS/AppleChu";
4143
private const string AppleChuAsset = "AppleChu.dll";
4244

@@ -59,11 +61,13 @@ public async Task<ActionResult> GetLatestVersions()
5961

6062
var binPath = string.IsNullOrEmpty(StaticSettings.GamePath) ? "" : Path.Combine(StaticSettings.GamePath, "bin");
6163
var loaderInstalled = !string.IsNullOrEmpty(binPath) && System.IO.File.Exists(Path.Combine(binPath, "version.dll"));
64+
var proxyInstalled = !string.IsNullOrEmpty(binPath) && System.IO.File.Exists(Path.Combine(binPath, "d3d9.dll"));
6265
var appleChuInstalled = !string.IsNullOrEmpty(binPath) && System.IO.File.Exists(Path.Combine(binPath, "mods", "AppleChu.dll"));
6366

6467
return Ok(new
6568
{
6669
loader = new VersionInfo(loader?.Tag_name ?? "", loaderInstalled ? "installed" : "", loader?.Assets.FirstOrDefault(a => a.Name == LoaderAsset)?.Browser_download_url ?? ""),
70+
proxy = new VersionInfo(loader?.Tag_name ?? "", proxyInstalled ? "installed" : "", loader?.Assets.FirstOrDefault(a => a.Name == ProxyAsset)?.Browser_download_url ?? ""),
6771
applechu = new VersionInfo(applechu?.Tag_name ?? "", appleChuInstalled ? "installed" : "", applechu?.Assets.FirstOrDefault(a => a.Name == AppleChuAsset)?.Browser_download_url ?? ""),
6872
});
6973
}
@@ -75,18 +79,25 @@ public async Task<ActionResult> InstallLoader([FromBody] InstallRequest? request
7579
if (string.IsNullOrEmpty(gamePath))
7680
return BadRequest("GamePath not set");
7781

78-
var url = request?.Url;
79-
if (string.IsNullOrEmpty(url))
82+
var release = await GetLatestRelease(LoaderRepo, LoaderAsset);
83+
84+
var loaderUrl = request?.Url;
85+
if (string.IsNullOrEmpty(loaderUrl))
86+
loaderUrl = release?.Assets.FirstOrDefault(a => a.Name == LoaderAsset)?.Browser_download_url;
87+
if (string.IsNullOrEmpty(loaderUrl))
88+
return NotFound("No release found");
89+
90+
var binPath = Path.Combine(gamePath, "bin");
91+
var loaderData = await Http.GetByteArrayAsync(loaderUrl);
92+
await System.IO.File.WriteAllBytesAsync(Path.Combine(binPath, "version.dll"), loaderData);
93+
94+
var proxyUrl = release?.Assets.FirstOrDefault(a => a.Name == ProxyAsset)?.Browser_download_url;
95+
if (!string.IsNullOrEmpty(proxyUrl))
8096
{
81-
var release = await GetLatestRelease(LoaderRepo, LoaderAsset);
82-
url = release?.Assets.FirstOrDefault(a => a.Name == LoaderAsset)?.Browser_download_url;
97+
var proxyData = await Http.GetByteArrayAsync(proxyUrl);
98+
await System.IO.File.WriteAllBytesAsync(Path.Combine(binPath, "d3d9.dll"), proxyData);
8399
}
84-
if (string.IsNullOrEmpty(url))
85-
return NotFound("No release found");
86100

87-
var data = await Http.GetByteArrayAsync(url);
88-
var dest = Path.Combine(gamePath, "bin", "version.dll");
89-
await System.IO.File.WriteAllBytesAsync(dest, data);
90101
return Ok();
91102
}
92103

ChuChartManager/Front/src/client/mod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import axios from 'axios'
33

44
export interface ModStatus {
55
loaderInstalled: boolean
6+
proxyInstalled: boolean
67
mods: { name: string; version: string }[]
78
}
89

@@ -57,6 +58,7 @@ export interface VersionInfo {
5758

5859
export interface LatestVersions {
5960
loader: VersionInfo
61+
proxy: VersionInfo
6062
applechu: VersionInfo
6163
}
6264

ChuChartManager/Front/src/views/ModManager.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const hasLoadedConfig = ref(false)
2323
2424
const appleChu = computed(() => status.value?.mods.find(mod => mod.name.toLowerCase() === MOD_ID.toLowerCase()))
2525
const loaderOk = computed(() => status.value?.loaderInstalled ?? false)
26+
const proxyOk = computed(() => status.value?.proxyInstalled ?? false)
2627
const modOk = computed(() => !!appleChu.value)
2728
const configOk = computed(() => !!manifest.value && !!config.value)
2829
@@ -103,7 +104,12 @@ watch(config, () => {
103104
<span :class="loaderOk ? 'c-green-6' : 'c-red-6'">{{ loaderOk ? t('mods.installed') : t('mods.notInstalled') }}</span>
104105
<Button v-if="!loaderOk" :disabled="installing" @click="doInstall('loader')">{{ t('mods.install') }}</Button>
105106

106-
<div class="w-8" />
107+
<div class="w-4" />
108+
109+
<span>d3d9 proxy:</span>
110+
<span :class="proxyOk ? 'c-green-6' : 'c-red-6'">{{ proxyOk ? t('mods.installed') : t('mods.notInstalled') }}</span>
111+
112+
<div class="w-4" />
107113

108114
<span>AppleChu:</span>
109115
<template v-if="modOk">

ChuChartManager/Resources/AppleChu/default_config.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,10 @@ Version = "1"
8686

8787
## 切换窗口闪退修复
8888
[DeviceLostFix]
89+
90+
## FPS 显示(需要 d3d9 proxy)
91+
#[FpsDisplay]
92+
93+
## 帧率锁定(需要 d3d9 proxy)
94+
#[FrameLock]
95+
#fps = 60

ChuChartManager/Resources/AppleChu/manifest.toml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ game_versions = ["2.45"]
1313
groups = [
1414
{ id = "common", label = { zh = "常用", en = "Common" }, sections = ["General", "SkipStartup", "FreePlay", "DisableTimer", "SkipMapAnimation"] },
1515
{ id = "gameplay", label = { zh = "游戏", en = "Gameplay" }, sections = ["UnlockTracks", "CustomTimers", "AllTimers999", "Autoplay"] },
16-
{ id = "display", label = { zh = "显示", en = "Display" }, sections = ["Unlock120fps", "Bypass1080p", "Bypass120hz", "DpiAware"] },
16+
{ id = "display", label = { zh = "显示", en = "Display" }, sections = ["Unlock120fps", "Bypass1080p", "Bypass120hz", "DpiAware", "FpsDisplay", "FrameLock"] },
1717
{ id = "audio", label = { zh = "音频", en = "Audio" }, sections = ["ForceSharedAudio", "Force2chAudio"] },
1818
{ id = "network", label = { zh = "网络", en = "Network" }, sections = ["DisableEncryption", "DisableTLS"] },
1919
{ id = "compatibility", label = { zh = "兼容", en = "Compatibility" }, sections = ["BypassAppUser"] },
@@ -166,3 +166,22 @@ id = "DeviceLostFix"
166166
always_enabled = true
167167
label = { zh = "切换窗口闪退修复", en = "Device lost fix" }
168168
description = { zh = "Alt+Tab 后防止游戏崩溃", en = "Prevent crash after Alt+Tab" }
169+
170+
[[config.sections]]
171+
id = "FpsDisplay"
172+
default_enabled = false
173+
label = { zh = "FPS 显示", en = "FPS display" }
174+
description = { zh = "需要 d3d9 proxy", en = "Requires d3d9.dll proxy" }
175+
176+
[[config.sections]]
177+
id = "FrameLock"
178+
default_enabled = false
179+
label = { zh = "帧率锁定", en = "Frame lock" }
180+
description = { zh = "需要 d3d9 proxy", en = "Requires d3d9.dll proxy" }
181+
[[config.sections.entries]]
182+
key = "fps"
183+
type = "int"
184+
default = 60
185+
min = 1
186+
max = 240
187+
label = { zh = "目标帧率", en = "Target FPS" }

0 commit comments

Comments
 (0)