- 桌面应用
- 游戏开发
【免费下载链接】Lumafly
A cross platform mod manager for Hollow Knight written in Avalonia.
Lumafly 是一款基于 Avalonia 开发的跨平台《空洞骑士》(Hollow Knight) 模组管理器,支持 Windows、macOS 与 Linux,并内置了英、西、葡、法、中、日、俄、波等语言界面。本文以仓库根目录的 README.md 为主线,结合 Lumafly 主工程源码与 Lumafly.Tests 测试用例,系统讲解它的安装使用、六大核心能力,以及"下载校验—安装切换—状态持久化—Modpack 分享"背后的完整实现链路。读完本文,你将既能独立完成从安装到管理 Mod 的全流程操作,也能理解其 modlinks 数据源、API 切换、URL Scheme 命令等底层机制,为二次开发或定制部署打下基础。
Lumafly 是什么:从 Scarab+ 到跨平台 Mod 管理器
按 README 的定位,Lumafly 是一个跨平台的《空洞骑士》Mod 管理器,前身是Scarab+(继承自早期 Scarab 项目),目前界面已完全本地化。README 明确列出的本地化语言为英语、西班牙语、葡萄牙语、法语、中文、日语、俄语与波兰语;而在源码层面,SupportedLanguages.cs 中的枚举还额外包含荷兰语(nl)与意大利语(it),即共支持 10 种语言,对应的本地化资源文件位于 Localizations 目录(含Resources.zh.resx等)。
从工程结构看(Lumafly.csproj),它基于:
- Avalonia 11.0.4+ Skia + Fluent 主题,实现跨平台 UI;
- .NET 7(
TargetFramework为net7.0,OutputType为WinExe); - ReactiveUI / PropertyChanged.SourceGenerator驱动 MVVM 视图模型;
- Mono.Cecil读取程序集元数据、HPackage.Net处理 Modpack 分享格式、NetSparkleUpdater负责 Windows 端自更新。
Program.cs 是启动入口:先完成日志初始化与语言探测,随后注册scarab://URL Scheme 处理器、注册 SIGTERM/SIGINT 信号处理,最后以经典桌面生命周期启动 Avalonia 应用。日志文件ModInstaller.log会写入配置目录,超过 5 MB 时自动归档,崩溃信息另存为ModInstaller_Error_*.log。
快速上手:从下载到进入游戏
README 的 Usage 一节给出了完整的用户操作路径,这也是每个玩家的标准使用流程:
- 下载安装:从官方下载页获取最新版本(或从 Releases 页面手动下载)。
- 搜索并安装:在 Mod 列表中搜索并下载你喜欢的 Mod。
- 进入游戏:安装完成后,Mod 会出现在游戏标题界面的左上角。
- 开关与更新:通过开关按钮启用/禁用某个 Mod 对游戏的影响;过期的 Mod 会显示橙色更新按钮,点击即可更新。
- 离线使用:无法联网时,可以以离线模式启动 Lumafly,此时仍可开关已安装的 Mod 与 Modding API。
需要补充的是,"Mod 出现在标题界面左上角"这一行为源自《空洞骑士》Modding API 的加载机制——Lumafly 只是负责把 Mod 文件放置到游戏目录并维护启用状态,真正让 Mod 生效的是游戏进程内加载的 API。
核心功能总览:README Features 完整解读
README 的 Features 一节定义了 Lumafly 的六大核心能力,下面逐条展开,并结合源码说明其实现方式。
1. 自动安装 Modding API,随时切换原版/Mod 版
Lumafly 会自动下载并安装 Mod 加载所必需的Modding API,并提供Toggle API按钮在"Mod 版游戏"与"原版游戏"之间切换。
实现上,ModDatabase.cs 会从官方 modlinks 拉取ApiLinks.xml,得到 API 的下载地址、版本号与 SHA256 哈希;Installer.cs 中的InstallApi/ToggleApi则负责实际安装与切换。切换的关键是游戏目录下三个文件名的"轮换":
Assembly-CSharp.dll—— 当前生效的程序集;Assembly-CSharp.dll.v—— 备份的原版程序集(vanilla);Assembly-CSharp.dll.m—— 备份的 Mod 版程序集(modded)。
ToggleApi的底层逻辑(Installer.cs)就是在这三个文件之间做文件移动:启用 API 时把原版Current移到.v、再从.m恢复 Mod 版;关闭 API 时反向操作。首次安装 API 时还会用FetchVanillaAssemblyLink按操作系统(Windows/macOS/Linux)下载对应的原版程序集备份,确保之后可以无损切回原版。
2. 搜索官方 modlinks 中的 300+ Mod
README 声称官方 modlinks 中收录了300 多个 Mod,Lumafly 提供统一的搜索、浏览入口。数据侧,ModDatabase每次启动都会抓取ModLinks.xml与ApiLinks.xml两个清单文件(请求超时 30 秒,失败自动回退到 jsdelivr CDN 镜像)。ModLinks.xml中每个<Manifest>条目被反序列化为 ModLinks.cs 中的Manifest记录,包含名称、版本、三个平台的下载链接与 SHA256、依赖、描述、标签、集成、作者等字段。
测试用例 DatabaseTest.cs 直接用一段内嵌的ModLinks.xml/ApiLinks.xml验证了这套反序列化逻辑:它断言QoL这个 Mod 的版本、依赖(Vasi)、下载链接等字段均被正确解析,且 API 版本号被正确读取为 63。这也是理解 modlinks 数据格式最直接的示例。
3. Modpack 分组与分享命令
Lumafly 允许把一组 Mod 打包成Modpack(配置文件/合集)并分享。本地实现位于 PackManager.cs:每个 Modpack 对应游戏目录下的一个文件夹,内含packMods.json清单(packInfoFileName常量)。支持叠加加载(additive,把包内 Mod 合并进当前列表)与独占加载(exclusive,清空现有 Mods 目录后整体替换),加载前会先把旧 Mod 目录缓存到Temp_Mods_Storage,失败时自动回滚。
分享则通过 URL Scheme 命令(README 指向的 Commands 文档)完成:把包转换为HPackageJSON 格式后上传到在线文本存储(实现为 PastebinTextStorage.cs),得到一个分享码,其他人用scarab://modpack/<code>即可导入。此外还支持把包导出为.zip文件。
4. 展示最近更新/新发布的 Mod
README 提到 Lumafly 能"Display mods that were recently updated or released"。这由 ModLinksChanges.cs 实现:它从静态资源仓库的ModlinksChanges.json获取"本周/本月新增与更新"的 Mod 名单,再结合上次使用的ModLinks.xml与当前清单做差量对比,得出"今天的改动",最终在界面上标记ModChangeState.New / Updated(枚举见 ModChangeState.cs)并按其排序权重展示。
5. 一站式管理:下载、更新、设置、Readme、报 Bug
单个 Mod 的详情操作非常完整,全部集中在 ModItem.cs 的ModItem模型上:
OnInstall/OnUpdate/Uninstall:安装、更新、卸载;OpenSettingsFile:直接打开该 Mod 的*.GlobalSettings.json配置文件(由 GlobalSettingsFinder.cs 在存档目录中定位,必要时会用 Mono.Cecil 反查 Mod 程序集中的类名,以匹配Modding.Mod、SFCore、Satchel等基类);OpenReadme/OpenReleaseNotes:弹出窗口查看 Readme 与更新日志;ReportBug:跳转到该 Mod 的 Issues 页面。
6. 手动安装非 modlinks 的 Mod
modlinks 之外的第三方 Mod 通过"手动安装"入口支持。这类 Mod 在源码中以NotInModLinksState(见 ModState.cs)标识,ModlinksMod字段区分"官方清单里有同名项但本地装的是自定义版本"与"完全自定义的 Mod"两种情况;列表中对它们会显示"not from official modlinks"的说明。
配置系统:HKInstallerSettings.json 全参数说明
Lumafly 的配置持久化在 Settings.cs 中定义,配置文件位于系统应用数据目录下的HKModInstaller文件夹(Windows 为%APPDATA%,Linux 为~/.config,macOS 为~/Library/Application Support),文件名是HKInstallerSettings.json,采用缩进 JSON 序列化。常用配置项如下表:
| 配置项 | 类型 / 默认值 | 说明 |
|---|---|---|
ManagedFolder | 字符串 | 《空洞骑士》游戏安装目录(即Managed目录所在位置) |
AutoRemoveUnusedDeps | Never(默认)/Ask/Always | 是否自动移除卸载后不再被依赖的 Mod(AutoRemoveUnusedDepsOptions.cs) |
WarnBeforeRemovingDependents | 布尔,默认true | 移除某 Mod 前是否警告其依赖方 |
UseCustomModlinks | 布尔,默认false | 是否使用自定义 modlinks 数据源 |
CustomModlinksUri | 字符串,默认空 | 自定义 modlinks 的地址 |
UseGithubMirror | 布尔,默认false | 是否通过 GitHub 镜像下载 |
GithubMirrorFormat | 字符串,默认空 | 镜像 URL 模板 |
PreferredLanguage | 可空枚举,默认自动探测 | 首选语言(取值为 SupportedLanguages.cs 的 10 种语言之一) |
LowStorageMode | 布尔,默认false | 低存储模式:不缓存下载的 Mod 压缩包 |
RequiresWorkaroundClient | 布尔 | 是否强制使用 IPv4 专用 HTTP 客户端(网络兼容性开关) |
Settings.Load()在 JSON 损坏时会静默回退为空配置而不是崩溃。此外,Program.cs 的SetPreferredLanguage会优先读取该配置,否则跟随系统区域语言,再次兜底为英语。
游戏目录的自动定位同样在Settings中完成:先遍历内置的静态路径列表(Steam / Xbox / GOG 的常见安装路径),再检查用户主目录下的 Linux(含 Flatpak)与 macOS 路径,最后在 Windows 上读取注册表(Valve Steam 的libraryfolders.vdf与 GOG 注册表键)来定位游戏库。也就是说,即使玩家把游戏装到了非默认位置,Lumafly 也能大概率自动找到。
安装、更新与卸载的实现原理
Installer是操作游戏目录的核心服务(Installer.cs),安装流程可以概括为:
- 确保 Modding API 已安装(递归调用
InstallApi); - 通过信号量(
SemaphoreSlim)串行化安装操作; - 递归处理依赖:
_Install会遍历mod.Dependencies,先装好每个依赖及其传递依赖; - 下载 Mod 文件(支持进度回调),下载前优先命中本地缓存(
CacheFolder下的HKInstallerCache); - 用 manifest 中声明的SHA256 哈希做完整性校验,不匹配则抛
HashMismatchException并中止; - 按文件类型落盘:
.zip解压(解压过程会做路径穿越防护,file_dest.StartsWith(dest_dir_path)检查防止恶意压缩包逃逸出目录),.dll直接写入Mods/<ModName>/; - 更新内存状态并写入持久化文件。
更新(OnUpdate)本质是带clearDlls标志的重装:先清空 Mod 文件夹中的旧 DLL 再放置新文件,避免残留旧程序集;卸载(_Uninstall)则直接删除对应目录,并把NotInModLinksState的 Mod 从列表移除。
状态模型是理解 UI 的关键。ModState.cs 定义了三种状态:
NotInstalledState:未安装;InstalledState:已安装(含Enabled启用、Version本地版本、Updated是否最新、Pinned置顶);NotInModLinksState:已安装但不在官方清单中(区分ModlinksMod)。
当清单版本与本地版本一致时Updated=true,否则UpdateAvailable为真,界面上就会显示橙色更新按钮。
开关 Mod 与 API:目录搬运与文件轮换
启用/禁用 Mod 的实现非常朴素且可靠:整体移动文件夹。_Toggle(Installer.cs)把 Mod 目录在Mods(启用)与Disabled(禁用)两个目录之间移动——游戏只加载Mods目录下的内容,因此禁用不会丢失任何文件,可以随时切回。
值得注意的两个细节:
- 启用时自动带起依赖:
Toggle在启用某 Mod 前,会先递归启用它的所有依赖(源码注释明确说明这是为了避免"启用后因缺少依赖而失效"); - 目标目录冲突保护:如果目标目录已存在同名文件夹,会弹窗询问用户是否删除冲突项。
API 的开关则使用前面提到的.v/.m/Current三文件轮换,且由独立的_modToggleSemaphore保护,避免与 Mod 切换并发冲突。
已安装状态持久化与自恢复
InstalledMods.cs 负责把"已安装哪些 Mod、启用状态如何、API 状态如何"持久化为配置文件目录下的InstalledMods.json。它有两个值得称道的健壮性设计:
- 损坏自恢复:JSON 损坏或首次安装时,会扫描
Mods/Disabled目录重建状态,版本未知的 Mod 标记为"过期"(Updated=false)并提示更新; - 目录状态对账:每次加载都会把磁盘目录与记录状态做对比——玩家手动移动、删除文件夹后,状态记录会被自动修正(源码中
enabled state mismatch, fixing!与Removing missing mod的 Trace 日志即出自此处)。
ModSourceTest.cs(ModSourceTest.cs)用内存文件系统验证了"记录安装状态 → 从 manifest 判断是否过期 → 记录卸载"的完整闭环,是对这套持久化逻辑的直接测试佐证。
Modpack 机制:分组、导入导出与分享
PackManager 是 Modpack 功能的核心(PackManager.cs),核心机制包括:
- 保存:
SavePack把当前Mods目录(排除Disabled)复制到ManagedFolder/<包名>/,并写入packMods.json(含名称、描述、作者与启用状态的 Mod 清单); - 加载:
LoadPack区分叠加与独占两种模式,加载前用CacheOldModsFolder备份当前 Mods 目录,任何一步失败都会RevertToPreviousModsFolder完整还原; - 导出:
SavePackToZip借助系统保存对话框把包目录压缩为.zip; - 导入/分享:
ConvertToHPackage用 HPackage.Net 把包序列化为 Hollow Knight 标准包格式 JSON,上传在线文本存储后得到SharingCode;ImportPack则反向解析分享码导入,重名包会被拒绝。
Pack模型定义在 Pack.cs,IsSame/DeepCopy用于编辑后判断是否发生变化。加载包前还会检测游戏进程(hollow_knight)是否在运行,必要时提醒用户关闭游戏。
URL Scheme 命令:远程控制与分享的通道
README 中提到的 "commands" 即scarab://自定义协议。注册与解析在 UrlSchemeHandler.cs:Windows 上写注册表HKEY_CURRENT_USER\SOFTWARE\Classes\scarab,Linux 上生成scarab.desktop桌面条目(x-scheme-handler/scarab),macOS 则在编译期写入Info.plist(见 Scripts/Lumafly.app/Contents/Info.plist)。
支持的命令(枚举定义见 UrlSchemeCommands.cs)如下:
| 命令 | 用途 |
|---|---|
download | 下载一个或多个 Mod,格式为scarab://download/名称:'链接'/名称2:'链接2' |
reset | 重置已安装状态 |
forceUpdateAll | 强制更新全部 Mod |
customModLinks | 切换并使用自定义 modlinks |
useOfficialModLinks | 切回官方 modlinks |
removeAllModsGlobalSettings | 清空所有 Mod 的全局设置文件 |
removeGlobalSettings | 移除指定 Mod 的全局设置文件 |
launch | 启动游戏 |
modpack | 导入某个分享码对应的 Modpack |
location | 定位/指定游戏目录 |
download命令的解析器ParseDownloadCommand会对名称做非法字符校验、对链接做 URI 合法性校验,非法输入直接拒绝解析;非scarab://前缀或未知命令会弹出警告框。ModItem.Share()方法会把单个 Mod 编码进分享链接,与 modpack 分享形成闭环。
“最近更新”与反向依赖搜索
- 最近更新:由
ModLinksChanges服务完成(详见上文功能 4),其IsLoaded三态布尔(null未加载 /true成功 /false失败)确保数据异常时界面不做无意义的展示;离线模式或使用自定义 modlinks 时该功能自动关闭。 - 反向依赖搜索:ReverseDependencySearch.cs 提供三类查询:
GetAllDependentAndIntegratedMods(依赖方 + 集成方)、GetAllIntegratedMods(仅集成方)、GetAllEnabledDependents(仅已启用的依赖方),且依赖关系支持传递(递归判断)。这与 UI 中的SearchType(Normal / DependencyAndIntegration / Integration,见 SearchType.cs)以及ModFilterState(All / Installed / Enabled / OutOfDate / WhatsNew,见 ModFilerState.cs)筛选器配合,能快速回答"卸载这个 Mod 会影响谁"、"哪些 Mod 集成了这个 Mod"等实际问题。
本地化与字体
本地化采用 Avalonia 标准的.resx资源机制(Lumafly.csproj 中把所有Localizations\*.resx设为嵌入资源),翻译工作通过 Crowdin 平台协作完成(README Contributions 一节有说明)。Program.cs 还针对不同语言做了字体覆盖:中文使用内嵌的 Noto Sans SC、其余语言使用 Noto Sans(字体文件位于 Assets/Fonts),确保 CJK 字符渲染正常。
网络容错与离线模式
- 离线模式:
LumaflyMode枚举(LumaflyMode.cs)区分Online/Offline。离线启动时不拉取任何在线数据,仅基于本地InstalledMods.json与已下载缓存工作,仍可开关 Mod 与 API——这正是 README 描述的离线能力。 - IPv4 回退客户端:WorkaroundHttpClient.cs 针对 .NET 默认双栈 socket 在某些网络/驱动下走 IPv6 失败的问题,提供了强制 IPv4 连接的替代客户端;
RequiresWorkaroundClient为 true 时全程使用,否则先试常规客户端、超时再回退(HttpSetting.OnlyWorkaround / TryBoth)。
自更新机制
AppUpdater.cs 负责应用自更新:Windows 端基于 NetSparkleUpdater 读取 appcast.xml(仓库根目录,当前最新条目为 v3.3.0.0),支持自动下载安装、重启后替换;非 Windows 平台改为手动检查 GitHub Releases 的tag_name版本号,高于本地版本时提示用户跳转下载。更新信息(发布说明、下载链接、变更日志)通过静态资源仓库的UpdateLinks.json动态下发,无需发版即可调整。
测试保障
仓库自带的 Lumafly.Tests 覆盖了最关键的两条链路:
- DatabaseTest.cs:验证
ModLinks.xml/ApiLinks.xml的 XML 反序列化、ModDatabase的 Item 构建以及三种状态(未安装 / 已安装 / 过期)的判定; - ModSourceTest.cs:验证
InstalledMods的持久化读写与"版本一致即最新"逻辑。
它们使用System.IO.Abstractions.TestingHelpers的内存文件系统,可在无真实游戏目录的情况下运行,也间接证明了核心逻辑与具体文件系统解耦。
参与贡献与社区生态
按 README 的 Contributions 说明:功能建议与 Bug 请走 Issues 页面;想参与开发可关注 enhancement 标签下的待办功能;本地化翻译请通过 Crowdin 平台提交。README 的 Credits 部分同时列出了项目渊源——基于 fifty-six 的 Scarab 开发,以及来自社区的多语言译者与美术作者。
结语
从 README 的六项核心特性出发,本文结合仓库源码把 Lumafly 拆解为一条清晰的实现主线:modlinks 数据源驱动内容、Installer 负责文件级安装与切换、InstalledMods 持久化状态、PackManager 支持批量管理、URL Scheme 打通远程分享、离线模式兜底断网场景。无论你是普通玩家想正确安装和使用它,还是开发者想为《空洞骑士》生态贡献一个 Mod 管理器插件或定制版本,都可以从 README.md 起步,再按本文给出的源码路径逐层深入。
- 桌面应用
- 游戏开发
【免费下载链接】Lumafly
A cross platform mod manager for Hollow Knight written in Avalonia.
相关推荐
Lumafly:跨平台空洞骑士模组管理完全指南
Lumafly:跨平台空洞骑士模组管理完全指南 您是否曾为安装空洞骑士模组时的繁琐步骤感到困扰?Lumafly作为一款基于Avalonia开发的跨平台模组管理工
桌面应用游戏开发Lumafly:跨平台空洞骑士模组管理完全指南
Lumafly:跨平台空洞骑士模组管理完全指南 您是否曾为安装空洞骑士模组时的繁琐步骤感到困扰?Lumafly作为一款基于Avalonia开发的跨平台模组管理工
桌面应用游戏开发Lumafly:跨平台空洞骑士模组管理完全指南
Lumafly:跨平台空洞骑士模组管理完全指南 Lumafly是一款基于Avalonia开发的跨平台模组管理工具,专门为《空洞骑士》游戏设计。它让玩家能够轻松管
桌面应用游戏开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考