# 开发指南 本文面向希望构建、调试或扩展 Space Engineers Blueprint Editor 的开发者。架构背景见[架构说明](ARCHITECTURE.md),提交约定见[贡献指南](../CONTRIBUTING.md)。 ## 环境要求 - Windows 10 1809(Build 17763)或更高版本,推荐 x64。 - Visual Studio 2022,安装“.NET 桌面开发”和 Windows 应用开发相关组件。 - .NET 8 SDK;更高版本 SDK 也可以面向 .NET 8 构建,但提交前应至少验证一次 .NET 8 环境。 - .NET Framework 4.8 Developer Pack,用于核心层和转换器。 - Microsoft Edge WebView2 Runtime,用于三维蓝图编辑页。 - 通过 Steam 安装的《Space Engineers》。 - Git。 主程序使用 Windows App SDK 的实验版依赖。若命令行构建出现 XAML 或 Windows App SDK 工具链问题,优先使用 Visual Studio 打开解决方案并确认相应组件已安装。 ## 获取代码 ```powershell git clone https://github.com/XFEstudio/SpaceEngineersBlueprintEditorInWinUI.git cd SpaceEngineersBlueprintEditorInWinUI dotnet restore SpaceEngineersBlueprintEditor.sln ``` 仓库不包含《Space Engineers》的程序集。还原 NuGet 包不需要游戏,解析核心项目引用和运行应用则需要有效游戏安装。 ## 游戏目录检测 构建逻辑位于 `Directory.Build.targets` 和 `build/Find-SpaceEngineers.ps1`。设置了 `UseSpaceEngineersAssemblies=true` 的项目会在解析引用前执行检测。 ```mermaid flowchart TD Begin["开始查找游戏"] --> ExplicitBin{"MSBuild SpaceEngineersBinPath"} ExplicitBin -->|"有效"| Validate["验证 Bin64 与 Content"] ExplicitBin -->|"无效或未设置"| ExplicitRoot{"MSBuild SpaceEngineersRootPath"} ExplicitRoot -->|"有效"| Validate ExplicitRoot -->|"未找到"| Env["SPACE_ENGINEERS_BIN / ROOT"] Env --> Registry["Steam 卸载注册表"] Registry --> Libraries["Steam libraryfolders.vdf"] Libraries --> Drives["固定磁盘 SteamLibrary 默认路径"] Drives --> Found{"找到有效目录?"} Validate --> Found Found -->|"是"| References["引用 Bin64 中的游戏 DLL"] Found -->|"否"| Error["MSBuild 报错并停止"] ``` 有效游戏根目录必须包含: - `Bin64\SpaceEngineers.exe` - `Bin64\VRage.Game.dll` - `Bin64\Sandbox.Game.dll` - `Bin64\SpaceEngineers.Game.dll` - `Content` 目录 ### 显式指定路径 临时传给一次构建: ```powershell dotnet build SpaceEngineersBlueprintEditor.sln -c Debug -p:Platform=x64 ` -p:SpaceEngineersBinPath="D:\SteamLibrary\steamapps\common\SpaceEngineers\Bin64" ``` 也可传游戏根目录: ```powershell dotnet build SpaceEngineersBlueprintEditor.sln -c Debug -p:Platform=x64 ` -p:SpaceEngineersRootPath="D:\SteamLibrary\steamapps\common\SpaceEngineers" ``` 为当前 PowerShell 会话设置环境变量: ```powershell $env:SPACE_ENGINEERS_ROOT = "D:\SteamLibrary\steamapps\common\SpaceEngineers" # 或 $env:SPACE_ENGINEERS_BIN = "D:\SteamLibrary\steamapps\common\SpaceEngineers\Bin64" ``` 可独立验证检测脚本: ```powershell powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass ` -File build\Find-SpaceEngineers.ps1 ``` 成功时脚本只输出规范化后的 `Bin64` 路径。 ### 运行时检测 `GameInstallationLocator` 在运行时使用类似顺序,但会优先尝试设置页保存的路径。`GameAssemblyLoader` 随后注册 `AssemblyResolve`,并通过 `SetDllDirectory` 让原生依赖可从 `Bin64` 解析。 由于程序集加载后无法在当前 `AppDomain` 中安全切换版本,更改设置页中的游戏目录后应重启应用。 ## 构建 推荐构建整个解决方案: ```powershell dotnet build SpaceEngineersBlueprintEditor.sln -c Debug -p:Platform=x64 --nologo ``` 发布前使用 Release: ```powershell dotnet build SpaceEngineersBlueprintEditor.sln -c Release -p:Platform=x64 --nologo ``` 也可在 Visual Studio 的配置管理器中选择 `Debug|x64` 或 `Release|x64` 后构建解决方案。 ### 构建时发生了什么 1. `GameAssemblyLoader` 同时构建 `net48` 与 `net8.0` 版本。 2. `SpaceEngineersCore` 以 `net48` 编译并引用游戏程序集。 3. `BlueprintConverter` 使用同一套游戏类型编译,作为独立辅助转换入口。 4. WinUI 主程序构建并引用加载器与核心层,同时打包本地 WebGL 编辑器资源。 5. WPF 安装器独立构建,不依赖游戏 DLL。 游戏引用设置了 `Private=false`,不会复制到输出目录。不要为“修复缺 DLL”而把 `Bin64` 批量复制进仓库或发布包。 ### 架构警告 部分游戏 DLL 是 AMD64,而核心项目当前生成 MSIL,因此 MSBuild 可能报告 `MSB3270`。实际运行与验证请使用 x64;若修改项目平台设置,应同时验证托管和原生依赖解析,不要仅隐藏警告。 ### .NET Framework 兼容性 `SpaceEngineersCore` 和 `BlueprintConverter` 面向 `net48`。在这两个项目中使用较新的 C# 语法时,要注意目标框架并不自带所有编译器辅助类型。例如 `record`、`init` 或带 `init` 的生成代码可能需要显式提供 `System.Runtime.CompilerServices.IsExternalInit` 兼容类型,否则会出现 `CS0518`。 ## 运行与调试 推荐把 `SpaceEngineersBlueprintEditor` 设为启动项目,并选择 x64。也可尝试命令行启动: ```powershell dotnet run --project SpaceEngineersBlueprintEditor\SpaceEngineersBlueprintEditor.csproj ` -c Debug -p:Platform=x64 ``` 启动时应用会并行执行两项耗时操作:扫描蓝图目录、初始化游戏定义。调试初始化问题时,可在以下位置设置断点: - `GameInstallationLocator.FindGameRootPath` - `GameAssemblyLoader.Initialize` - `App` 构造函数中的后台初始化任务 - `Initializer.Initialize` - `SpaceEngineersHelper.LoadDefinitionViewDataListAsync` ### 三维编辑器资源 三维页使用 `WebView2` 加载 `Assets\Blueprint3DEditor.html`。code-behind 把输出目录的 `Assets` 映射到 `https://blueprint-editor.local/`,所有 WebGL、选择和快捷键逻辑都来自本地文件,不需要外部网络。 发布时应确认该 HTML 被复制到输出目录,并保留 WebView2 Runtime 前置要求。C# 与页面通过 `PostWebMessageAsJson` / `WebMessageReceived` 交换紧凑场景和操作消息;修改协议时要同时更新模型、场景构建器和页面脚本。 正常保存已经直接调用核心层的原子 `Save` API,不依赖 `BlueprintConverter` 的发布布局。转换器仍随解决方案构建,如继续分发,应单独验证其运行依赖和输入信任边界。 ## 解决方案项目 | 项目 | 关键职责 | 主要依赖 | | --- | --- | --- | | `SpaceEngineersBlueprintEditor` | WinUI 页面、ViewModel、服务、导航和配置 | Windows App SDK、CommunityToolkit.Mvvm、核心层 | | `GameAssemblyLoader` | 构建期之外的游戏查找与运行时程序集解析 | Registry、Steam VDF、`AssemblyResolve` | | `SpaceEngineersCore` | 无窗口初始化、定义查询、ObjectBuilder 原子保存、尺寸/装甲转换和 Skeleton 形变 | 游戏 `Bin64` 和 `Content` | | `BlueprintConverter` | 独立 JSON 中间对象到 XML `.sbc`;主界面当前不依赖它保存 | Newtonsoft.Json、游戏序列化类型 | | `Installer` | 安装、升级、解压、快捷方式 | WPF、CommunityToolkit.Mvvm | | `Test` | 临时集成实验 | 核心层、游戏安装 | `SpaceEngineersBlueprintEditor.Tests` 当前只有测试源码片段,没有被解决方案引用的测试项目文件。请勿在文档或 CI 中把它描述成可运行的测试套件。 ## 代码组织 主程序采用 MVVM 风格: ```text SpaceEngineersBlueprintEditor/ ├─ Views/ # WinUI 页面及少量视图事件桥接 ├─ ViewModels/ # 页面状态与命令 ├─ Controls/ # 钣金形变等专用编辑控件 ├─ Model/ # 蓝图和定义的视图数据 ├─ Interface/Services/ # 服务契约 ├─ Implements/Services/ # 拖放、列表、树、背景等实现 ├─ Utilities/ # 路径、蓝图扫描、帮助类和选择器 ├─ Profiles/ # 持久配置与缓存配置 ├─ Strings/ # en-us、zh-cn 本地化资源 └─ Assets/ # 应用图标、图片和本地 WebGL 编辑器 ``` 页面由 `PageManager` 注册,导航和全局消息/加载状态由 WinUIHelper 的服务管理器协调。新页面应延续现有的 View + ViewModel 配对和服务注入方式。 ## 本地化 界面资源位于: ```text SpaceEngineersBlueprintEditor\Strings\en-us\Resources.resw SpaceEngineersBlueprintEditor\Strings\zh-cn\Resources.resw ``` 新增用户可见文本时: 1. 为英文和简体中文资源添加相同键。 2. XAML 优先使用 `x:Uid`。 3. C# 文本使用现有的 `GetLocalized()` 扩展。 4. 检查参数、标点和占位符在两种语言下均可读。 游戏定义名称由游戏自己的 Localization 内容加载,语言取当前线程的 UI Culture。 ## 验证 仓库尚无标准自动化测试套件,因此至少完成以下检查: 1. `Debug|x64` 全解决方案构建无错误。 2. 自动检测和显式路径两种方式均能找到游戏。 3. 应用启动后可以打开本地 `.sbc`。 4. 详情页能显示网格、方块和组件。 5. 编辑一个安全字段并保存,确认生成/更新 `sbcB5` 后游戏仍可读取结果。 6. 三维页能渲染、选择、变换、撤销并另存;钣金页能修改和重置测试方块的 Skeleton。 7. 尺寸/装甲转换能报告已转换和不支持数量,并在游戏测试世界验证。 8. 定义页四种分类都能加载并搜索。 9. 中英文资源键没有明显缺失。 10. 所有 Markdown 相对链接和 Mermaid 代码块可以渲染。 不要使用个人正式蓝图做破坏性测试;准备一个体积小、无 Mod 的测试蓝图副本。 ## 常见构建问题 ### `Space Engineers was not found` 运行检测脚本确认输出;若为空,使用 `SpaceEngineersBinPath` 或环境变量。路径可指向游戏根目录、`Bin64`,运行时选择器还接受 `SpaceEngineers.exe`。 ### `The detected Space Engineers installation is incomplete` 通过 Steam 验证游戏文件完整性,并确认你没有把 Dedicated Server 或其他目录当作客户端安装目录。 ### `CS0518 IsExternalInit` 检查最近加入 `net48` 项目的 `record`、`init` 或生成类型。改用普通类/`set`,或在兼容层中提供项目统一的 `IsExternalInit` 定义。 ### 启动或保存时缺少 DLL 确认应用能定位正确的游戏 `Bin64` 且进程为 x64。游戏 DLL 应从安装目录加载,而不是散落在输出目录;三维页单独报错时还应检查 WebView2 Runtime 和 `Assets\Blueprint3DEditor.html`。 ### 游戏更新后定义加载失败 先验证游戏文件,再清理并重新构建: ```powershell dotnet clean SpaceEngineersBlueprintEditor.sln -c Debug -p:Platform=x64 dotnet build SpaceEngineersBlueprintEditor.sln -c Debug -p:Platform=x64 ``` 若游戏 API 已变化,需要按新的程序集签名更新核心初始化桩和相关调用。