Skip to content

Commit bbbc200

Browse files
author
StArray
committed
refactor(core): 优化本地路径获取及渲染器检测逻辑
- 替换内嵌字体为 Noto Sans CJK 字体,提升多语言支持 - 使用 COREHOLD_TARGET_DIR 环境变量或默认路径确定 DLL 父路径 - 合并并简化本地 DLL 解析逻辑,自动识别 cimgui 库 - 改进日志文件写入加锁,保证线程安全 - 动态设置 Il2Cpp 库路径,兼容不同运行时后端 - 移除过时的渲染器检测代码,新增 RendererDetector 类统一检测图形设备类型 - 修改 ModManagerUI 初始化路径为动态获取的 DLL 父路径 - 精简渲染后端设置,默认使用 D3D11 后端,移除多后端支持代码 - 更新嵌入资源配置,替换字体资源文件名和引用路径
1 parent a2e20cb commit bbbc200

6 files changed

Lines changed: 68 additions & 109 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ StArray.ModManager/ C# core library (.NET 10)
4141
MonoReflection.cs Assembly/Class/Method/Field 反射
4242
Resources/ 嵌入资源
4343
fa-solid-900.ttf FontAwesome 7 图标字体
44-
msyh.ttf 微软雅黑字体
44+
NotoSansCJK-Regular.otf Noto Sans CJK 中日韩字体
4545
L10n.cs / Localization.* 本地化字符串
4646
Runtime/ Mod 框架接口
4747
HookAttributes.cs [UnmanagedHook] 特性

‎StArray.ModManager.Windows/Managed.cs‎

Lines changed: 17 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,22 @@ namespace StArray.ModManager.Windows;
1414

1515
public static class Managed
1616
{
17-
public static string AssemblyPath = string.Empty;
17+
static string DllParentPath = Environment.GetEnvironmentVariable("COREHOLD_TARGET_DIR") ?? AppContext.BaseDirectory;
18+
const int STD_OUTPUT_HANDLE = -11;
19+
static readonly Lock _writeLock = new();
1820

1921
static Managed()
2022
{
2123
NativeLibrary.SetDllImportResolver(typeof(Managed).Assembly, ResolveDll);
22-
NativeLibrary.SetDllImportResolver(typeof(ImGui).Assembly, (string libraryName, Assembly assembly, DllImportSearchPath? searchPath) =>
23-
{
24-
if (libraryName.Contains("cimgui"))
25-
{
26-
// cimgui symbols are compiled into StArray.ModManager.Windows.Native.dll,
27-
// which is already loaded by the native host before managed code runs.
28-
// Just return that module's handle — no filesystem path needed.
29-
var h = Win32Native.GetModuleHandleW(NativeApi.LibraryName + ".dll");
30-
if (h != IntPtr.Zero) return h;
31-
}
32-
return IntPtr.Zero;
33-
});
24+
NativeLibrary.SetDllImportResolver(typeof(ImGui).Assembly, ResolveDll);
3425
}
3526

36-
private static StreamWriter Writer = null;
27+
private static StreamWriter? Writer = null;
3728

3829
private static IntPtr ResolveDll(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
3930
{
4031
// Our own Native DLL is already loaded by the host — return its handle.
41-
if (libraryName == NativeApi.LibraryName)
32+
if (libraryName == NativeApi.LibraryName || libraryName == "cimgui")
4233
{
4334
var h = Win32Native.GetModuleHandleW(NativeApi.LibraryName + ".dll");
4435
if (h != IntPtr.Zero) return h;
@@ -71,71 +62,35 @@ public static int Entry(int argc, IntPtr argv)
7162
// args[0]: mods directory (from corehold.json entrypoint_string_args)
7263
string modsPath = args.Length > 0
7364
? Path.GetFullPath(args[0])
74-
: Path.Combine(AppContext.BaseDirectory, "..", "mods");
65+
: Path.Combine(DllParentPath, "..", "mods");
7566

76-
// Managed directory = where our DLLs live (AppContext.BaseDirectory for CoreCLR host)
77-
string managedDir = AppContext.BaseDirectory;
78-
AssemblyPath = Path.Combine(managedDir, typeof(Managed).Namespace + ".dll");
7967
if (!Directory.Exists(modsPath))
8068
Directory.CreateDirectory(modsPath);
81-
Writer = new StreamWriter(Path.Combine(Path.GetDirectoryName(modsPath), "log.txt"), append: false);
69+
lock (_writeLock)
70+
{
71+
Writer = new StreamWriter(Path.Combine(Path.GetDirectoryName(modsPath)!, "log.txt"), append: false);
72+
}
8273
Writer.AutoFlush = true;
8374
Logger.Info($"{nameof(Managed)}-Benchmark", $"Path resolve: {Benchmark.End():F3}s");
84-
85-
Il2CppFunctions.SetIl2CppLibraryPath(Path.Combine(AppContext.BaseDirectory,"..","..", "GameAssembly.dll"));
86-
// 检测运行时后端 (IL2CPP / Mono)
75+
8776
var backend = RuntimeManager.Detect();
8877
Logger.Info("Runtime", $"Detected backend: {backend}");
89-
78+
if (backend == RuntimeBackend.Il2Cpp)
79+
{
80+
Il2CppFunctions.SetIl2CppLibraryPath(Path.Combine(DllParentPath, "..", "..", "GameAssembly.dll"));
81+
}
9082
HookHelper.Instance = new MinHook();
91-
// 检测图形设备类型
92-
//var renderer = GetGameRenderer();
93-
//Logger.Info("Backend", $"Detected renderer: {renderer}");
94-
95-
ModManagerUI modManagerUI = new(new ModLoader(modsPath), managedDir);
83+
ModManagerUI modManagerUI = new(new ModLoader(modsPath), DllParentPath);
9684

9785
NativeApi.SetBackend(1); // D3D11
9886
ImGuiDXRenderer.OnRender += modManagerUI.Render;
9987
ImGuiDXRenderer.Install();
100-
/*if ((renderer & Renderer.D3D11) != 0)
101-
{
102-
NativeApi.SetBackend(1); // D3D11
103-
ImGuiRenderer.OnRender += modManagerUI.Render;
104-
ImGuiRenderer.Install();
105-
}
106-
else if ((renderer & Renderer.D3D12) != 0)
107-
{
108-
NativeApi.SetBackend(0); // D3D12
109-
ImGuiRenderer.OnRender += modManagerUI.Render;
110-
ImGuiRenderer.Install();
111-
}
112-
else if ((renderer & Renderer.D3D9) != 0)
113-
{
114-
NativeApi.SetBackend(2); // D3D9
115-
ImGuiRenderer.OnRender += modManagerUI.Render;
116-
ImGuiRenderer.Install();
117-
}
118-
else if ((renderer & Renderer.Vulkan) != 0 ||
119-
(renderer & Renderer.OpenGL) != 0)
120-
{
121-
// GL/VK: native handles Win32 init only, C# handles ImGui backend
122-
ImGuiRenderer.OnRender += modManagerUI.Render;
123-
ImGuiRenderer.Install();
124-
}
125-
else
126-
{
127-
Logger.Error("Backend", "No supported renderer found");
128-
return 1;
129-
}*/
13088

13189
totalSw.Stop();
13290
Logger.Info($"{nameof(Managed)}-Benchmark", $"=== Startup total: {totalSw.Elapsed.TotalSeconds:F3}s ===");
13391
return 0;
13492
}
13593

136-
const int STD_OUTPUT_HANDLE = -11;
137-
static readonly object _writeLock = new();
138-
13994
static void Write(string s)
14095
{
14196
lock (_writeLock)
@@ -144,48 +99,4 @@ static void Write(string s)
14499
Win32Native.WriteConsoleW(Win32Native.GetStdHandle(STD_OUTPUT_HANDLE), s, (uint)s.Length, out _, 0);
145100
}
146101
}
147-
148-
[Flags]
149-
public enum Renderer
150-
{
151-
None = 0,
152-
D3D12 = 1,
153-
D3D11 = 2,
154-
D3D9 = 4,
155-
OpenGL = 8,
156-
Vulkan = 16
157-
}
158-
159-
public static Renderer GetGameRenderer()
160-
{
161-
Renderer result = Renderer.None;
162-
163-
// Unity 2020+ GraphicsDeviceType 枚举值:
164-
// Direct3D9 = 0, Direct3D11 = 2, Direct3D12 = 3
165-
// OpenGLCore = 11, Vulkan = 13
166-
int gdt = GraphicsDevice.GetGraphicsDeviceType();
167-
switch (gdt)
168-
{
169-
case 0: result |= Renderer.D3D9; break;
170-
case 2: result |= Renderer.D3D11; break;
171-
case 3: result |= Renderer.D3D12; break;
172-
case 11: result |= Renderer.OpenGL; break;
173-
case 13: result |= Renderer.Vulkan; break;
174-
default:
175-
// 回退到模块名检测(非 Unity 或未知版本)
176-
if (Win32Native.GetModuleHandleW("d3d12.dll") != nint.Zero)
177-
result |= Renderer.D3D12;
178-
if (Win32Native.GetModuleHandleW("d3d11.dll") != nint.Zero)
179-
result |= Renderer.D3D11;
180-
if (Win32Native.GetModuleHandleW("d3d9.dll") != nint.Zero)
181-
result |= Renderer.D3D9;
182-
if (Win32Native.GetModuleHandleW("opengl32.dll") != nint.Zero)
183-
result |= Renderer.OpenGL;
184-
if (Win32Native.GetModuleHandleW("vulkan-1.dll") != nint.Zero)
185-
result |= Renderer.Vulkan;
186-
break;
187-
}
188-
189-
return result;
190-
}
191102
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using StArray.ModManager.RuntimeAbstractions;
3+
using StArray.ModManager.Windows.Native;
4+
5+
namespace StArray.ModManager.Windows;
6+
7+
[Flags]
8+
public enum Renderer
9+
{
10+
None = 0,
11+
D3D12 = 1,
12+
D3D11 = 2,
13+
D3D9 = 4,
14+
OpenGL = 8,
15+
Vulkan = 16
16+
}
17+
18+
public static class RendererDetector
19+
{
20+
public static Renderer GetGameRenderer()
21+
{
22+
Renderer result = Renderer.None;
23+
24+
int gdt = GraphicsDevice.GetGraphicsDeviceType();
25+
switch (gdt)
26+
{
27+
case 0: result |= Renderer.D3D9; break;
28+
case 2: result |= Renderer.D3D11; break;
29+
case 3: result |= Renderer.D3D12; break;
30+
case 11: result |= Renderer.OpenGL; break;
31+
case 13: result |= Renderer.Vulkan; break;
32+
default:
33+
if (Win32Native.GetModuleHandleW("d3d12.dll") != nint.Zero)
34+
result |= Renderer.D3D12;
35+
if (Win32Native.GetModuleHandleW("d3d11.dll") != nint.Zero)
36+
result |= Renderer.D3D11;
37+
if (Win32Native.GetModuleHandleW("d3d9.dll") != nint.Zero)
38+
result |= Renderer.D3D9;
39+
if (Win32Native.GetModuleHandleW("opengl32.dll") != nint.Zero)
40+
result |= Renderer.OpenGL;
41+
if (Win32Native.GetModuleHandleW("vulkan-1.dll") != nint.Zero)
42+
result |= Renderer.Vulkan;
43+
break;
44+
}
45+
46+
return result;
47+
}
48+
}
14.3 MB
Binary file not shown.

‎StArray.ModManager/StArray.ModManager.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
<ItemGroup>
2626
<EmbeddedResource Include="Resources\fa-solid-900.ttf" />
27-
<EmbeddedResource Include="Resources\msyh.ttf" />
27+
<EmbeddedResource Include="Resources\NotoSansCJK-Regular.otf" />
2828
</ItemGroup>
2929

3030
</Project>

‎StArray.ModManager/UI/IImGuiRenderer.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private static unsafe void LoadEmbeddedFont(ImGuiIOPtr io)
4949
{
5050
var asm = typeof(IImGuiRenderer).Assembly;
5151
using var stream = asm.GetManifestResourceStream(
52-
"StArray.ModManager.Resources.msyh.ttf");
52+
"StArray.ModManager.Resources.NotoSansCJK-Regular.otf");
5353
if (stream == null) return;
5454

5555
var ttf = new byte[stream.Length];

0 commit comments

Comments
 (0)