黑金古刀-永劫助手(BlackGoldAncientSword)——《永劫无间》战绩查询与队友识别桌面工具
中文 | English
黑金古刀-永劫助手(BlackGoldAncientSword)
- GitHub 仓库:https://github.com/ViewSuSu/BlackGoldAncientSword
- Gitee 镜像:https://gitee.com/SususuChang/BlackGoldAncientSword
一款基于 WPF + .NET 10 的开源桌面工程项目,围绕《永劫无间》公开的对局数据 API 做可视化展示,并系统化演示 Prism 模块化、Windows Graphics Capture、进程内 OCR 推理、Roslyn 源码生成、独立自更新等桌面工程实践。
该项目受到 Zzaphkiel/Seraphine 的鼓舞,感谢先驱者们做出的贡献。
项目介绍视频 🎬
项目介绍视频(Bilibili)
点击上方按钮观看项目介绍视频。
下载 📥
下载最新版本安装包
点击上方按钮即可直接下载最新版本的 .exe 安装包。
用户手册
简介黑金古刀-永劫助手(BlackGoldAncientSword)是一款运行在 Windows 10/11 上的开源 WPF 桌面项目,演示如何用 .NET 10 + WPF + Prism 组合搭建一个模块化、可自更新、内置离线 OCR 推理的完整桌面应用。项目本身也是一份公开数据可视化工具:通过第三方公开 API 拉取并展示玩家的历史对局统计,支持按三排 / 双排 / 单排及排位 / 匹配 / 天人模式的完整数据展示。
战绩查询战绩页面通过第三方公开 API(https://naraka.drivod.top/)拉取指定玩家的公开对局统计数据,并在 WPF 界面按赛季 / 模式 / 队伍规模维度进行结构化展示:
- 赛季数据总览:K/D、第一率、前五率、场均击败、场均治疗、场均助攻、场均生存
- 最高记录:最高击败、最高治疗、最高助攻、最高伤害、最多振刀
- 段位信息:当前赛季段位分数与段位名称(天选模式含星数)
- 最近 10 场对局:每局英雄、模式、击败/伤害、段位分变化(含 ± 差值)、荣誉称号
支持切换赛季、模式类别(排位 / 匹配 / 天人)和队伍规模(三排 / 双排 / 单排)。
战绩
点击玩家昵称旁的复制按钮可快速复制昵称或 UID。
—## 队伍信息展示
本模块演示如何用 Windows Graphics Capture API 对指定桌面窗口进行截图,交给进程内 ONNX Runtime 跑 PP-OCRv5 模型识别文字,再把识别结果对接到上游公开 API 做并列展示。
- 通过 OCR 自动读取截图中的文字,无需手动输入
- 支持三排 / 双排 / 单排队伍
- 支持排位 / 匹配 / 天人模式切换
- 多份识别结果并排展示,方便对比
- 状态切换后锁定当前展示内容,避免重复触发 OCR
队伍信息识别 1
队伍信息识别 2
设置
设置页面集中管理应用配置:
- 数据保存路径:战绩数据的本地存储目录(支持自定义 + 旧数据自动迁移)
- 缓存路径:图片缓存目录(含缓存大小显示与一键清理)
- 语言:支持 简体中文 / English / 繁體中文
- 关闭行为:点击关闭按钮时的默认行为,可选"每次询问 / 最小化到任务栏 / 最小化到系统托盘 / 直接退出",并支持记住选项
- 英雄选择时的右下角队伍提示弹窗:开关控制
- 检查更新:手动检查与下载新版本(调用独立的 Update 程序在线更新,详见下文)
- 当前版本:显示版本号
设置
在线更新
助手在启动时和"设置 → 检查更新"中均会自动比对 GitHub Releases 的最新版本。检测到新版本时会弹出更新提示页面,点击"在线更新"即可:
- 主程序拉起独立的BlackGoldAncientSword.Update.exe(更新器)并传入下载地址、安装目录、主程序文件名等参数;
- 更新器下载新版 zip → 解压 → 全量覆盖安装目录 → 重新拉起主程序 → 自身退出。
更新器与主程序完全解耦(不引用 App / Framework / Modules),因此覆盖文件时不会被 DLL 锁定。
其他功能
系统托盘程序支持最小化到系统托盘,长时间后台运行不占用任务栏。右键托盘图标可快速恢复窗口或退出。
关闭提示
- 托盘图标显示在线状态
- 点击关闭按钮时弹出确认对话框,提醒退出后将不再刷新数据
常见问题 FAQ 🧐Q:查询失败或数据有延迟?
数据来自第三方公开 APIhttps://naraka.drivod.top/,本项目仅做展示。查询失败通常是上游 API 服务本身的问题,本项目暂无法直接处理。
Q:OCR 识别失败或不准确?
OCR 使用 Windows Graphics Capture API 截取指定窗口的画面,目前只支持屏幕分辨率与窗口分辨率一致的情况。当两侧出现黑边时识别效果会受影响,建议使用与显示器同分辨率的全屏窗口运行。
OCR 对少量特殊字符可能识别不完整,可以在界面上手动修正后再触发查询。
Q:为什么安装包/程序这么大?
程序采用自包含发布(self-contained),内置了 .NET 运行时,无需用户额外安装 .NET 环境即可直接运行。此外,程序自带的 OCR 文字识别引擎依赖PP-OCRv5 ONNX 模型(约 22MB)+ ONNX Runtime 原生库 + SkiaSharp 图像编解码库,这部分总计约 50MB。这些原生 AI/视觉组件连同 .NET 运行时占了安装包的大部分体积。没有它们就无法实现队友昵称的自动截图识别,所以"庞大"是必要的代价 😅。
v1.0.0.3 起,OCR 引擎已从 PaddleOCR-json 子进程方案(含约 150MB Paddle Inference + MKL + OpenCV 原生 dll)切换到 RapidOcrNet 进程内 ONNX Runtime 方案,识别模型升级至 PP-OCRv5,安装包整体减重约 100MB,对特殊字符(如日文假名、拉丁扩展)的覆盖也大幅提升。Q:为什么屏幕会出现黄色边框?
黄色边框是程序进行窗口截图时的视觉提示,属于正常现象。
Q:如果被杀毒软件提示怎么办?
因为该程序没有被签名过,所以可能会被 360 等程序识别为病毒或者其他。可以关闭杀毒软件后重新打开。
**Q:在线更新失败怎么办?**更新器(BlackGoldAncientSword.Update.exe)独立于主程序运行,常见失败原因:网络无法访问下载源、安装目录权限不足、杀毒软件拦截覆盖。可从 Releases 页面直接下载安装包手动覆盖安装。
免责声明 📢
BlackGoldAncientSword(黑金古刀)未经 24 Entertainment 或网易认可,不代表 24 Entertainment、网易或任何官方参与制作或管理《永劫无间》产品的人的观点或意见。《永劫无间》及其所有关联产物均为 24 Entertainment / 网易的商标或注册商标。
点个 Star 支持我们 ⭐
开发者文档
解决方案概览
src/BlackGoldAncientSword.slnx共包含11 个项目:8 个类库 + 3 个可执行程序(主程序 App、独立更新器 Update、离线下载器 Downloader)。
┌────────────────────────────────────────────────────────┐ │ BlackGoldAncientSword.App │ ← WPF 主程序入口(WinExe) │ (Shell / MainWindow / Tray) │ └──────────┬─────────────────────────────────────────┬───┘ │ 启动外部进程 │ ▼ │ ┌──────────────────────────┐ │ │ BlackGoldAncientSword. │ │ │ Update (独立更新器,WinExe)│ │ │ 下载/解压/覆盖/重启 │ │ └──────────────────────────┘ │ │ ┌──────────────────────────┐ ← 独立发布,非主程序运行时依赖 │ BlackGoldAncientSword. │ │ Downloader (离线下载器, │ Gitee 分卷安装包下载 → │ WinExe) │ 拉起 Setup 完成安装 └──────────────────────────┘ │ ┌─────────────────────┬──────────────────────┘ │ │ ▼ ▼ ▼ ┌────────────┐ ┌──────────────┐ ┌───────────┐ │ Modules │ │ Framework │ │ Resources │ │ (10 个 UI │ ◄────► │ (Core + 13 │ ◄──────│ (多语言 │ │ 页面模块) │ │ 个服务接口) │ │ XAML+图) │ └─────┬──────┘ └──────┬───────┘ └───────────┘ │ │ │ ┌────────┴───────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌────────────────────┐ │ GameMonitor │ │ ScreenCapture│ │ Framework. │ │ (进程/日志/ │ │ (WGC API + │ │ SourceGenerator │ │ 状态机) │ │ 原生 DLL) │ │ (编译期生成 HTTP) │ └──────┬───────┘ └──────┬───────┘ └────────────────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────────┐ │ Ocr │ │ RapidOcrNet + │ │ (进程内 ONNX)│ │ PP-OCRv5 (ONNX) │ └──────────────┘ └──────────────────┘项目分层
| 层 | 项目 | 输出类型 | 职责 |
|---|---|---|---|
| 主程序 | BlackGoldAncientSword.App | WinExe | WPF 应用入口、主窗口、侧边栏导航、托盘、启动更新器、启动期后台预热 OCR |
| 更新器 | BlackGoldAncientSword.Update | WinExe | 独立在线更新进程,零业务依赖(仅 HandyControl) |
| 离线下载器 | BlackGoldAncientSword.Downloader | WinExe | 独立单文件 exe,从 Gitee release 顺序流式下载分卷安装包 → 拉起 Setup.exe → 自身退出。零 API 依赖(走 302 + CDN) |
| UI 模块 | BlackGoldAncientSword.Modules | ClassLib | 10 个 PrismIModule页面,按需加载 |
| 核心框架 | BlackGoldAncientSword.Framework | ClassLib | MVVM 基类、Prism 基础设施、服务抽象与实现、HTTP API |
| 游戏监控 | BlackGoldAncientSword.GameMonitor | ClassLib | 进程检测、Player.log 解析、战局状态机 |
| 屏幕捕获 | BlackGoldAncientSword.ScreenCapture | ClassLib | Windows Graphics Capture API + SharpDX,含原生 wgc_capture.dll |
| OCR 引擎 | BlackGoldAncientSword.Ocr | ClassLib | RapidOcrNet(PP-OCRv5 ONNX)进程内推理封装 |
| 资源 | BlackGoldAncientSword.Resources | ClassLib | 多语言 XAML 资源字典、图标、图片 |
| 源码生成 | BlackGoldAncientSword.Framework.SourceGenerator | Roslyn Analyzer | 编译期从 JSON 定义生成 HTTP 客户端与测试代码 |
| 测试 | BlackGoldAncientSword.Tests | xUnit | OCR、屏幕捕获、游戏监控、HTTP、更新流程测试 |
技术栈
| 类别 | 技术 / 库 | 用途 |
|---|---|---|
| 运行时 | .NET 10.0 (net10.0-windows) | 目标框架 |
| UI | WPF + HandyControl 3.5 | 桌面界面与控件库 |
| 主题 | 自定义 ModernTheme(青瓷竹青护眼配色) | 淡雅护眼浅绿底 + 竹青深绿点缀 + 深墨字,长时间阅读舒适 |
| MVVM 框架 | Prism 8.1 (Prism.DryIoc) | DI 容器、区域导航、模块化 |
| HTTP | 编译期源码生成器 | 从api-definitions.json自动生成强类型 API 客户端 |
| 对象映射 | Mapster 7.4 | DTO ↔ ViewModel |
| JSON | System.Text.Json(含源码生成上下文) | 序列化 / 反序列化(已全量替换 Newtonsoft.Json) |
| 屏幕捕获 | SharpDX.Direct3D11 + 原生 WGC DLL (C++/WinRT) | 游戏窗口截图 |
| OCR | RapidOcrNet 2.0.0 + ONNX Runtime 1.24(进程内推理,PP-OCRv5 模型) | 多语言文字识别(中/英/日/拉丁/西里尔等单模型覆盖) |
| 图像处理 | SkiaSharp 3.119 | OCR 入口 byte[] → SKBitmap 解码 |
| 系统托盘 | Hardcodet.NotifyIcon.Wpf | 托盘图标与菜单 |
| 测试 | xUnit + Moq | 单元测试与集成测试 |
| 打包 | Self-Contained + PublishSingleFile | App、Updater 均为单文件独立部署 (win-x64) |
| 安装包 | Inno Setup | 生成BlackGoldAncientSword-{version}-win-x64-Setup.exe |
目录结构
src/ ├── BlackGoldAncientSword.App/ # WPF 主程序入口(WinExe) │ ├── App.xaml / App.xaml.cs # 应用入口、Prism 启动配置 │ └── Shell/ │ ├── MainWindow.xaml(.cs) # 主窗口(侧边栏 + 导航 + 托盘) │ └── MainWindowViewModel.cs # 导航命令、游戏状态、更新检测 │ ├── BlackGoldAncientSword.Update/ # 独立在线更新器(WinExe,零业务依赖) │ ├── App.xaml(.cs) # 入口:解析 --url / --target / --main-exe │ ├── Services/ │ │ ├── UpdateOptions.cs # 命令行参数模型 │ │ └── UpdaterRunner.cs # 编排:下载→解压→关主程序→覆盖→重启 │ ├── Shell/UpdateWindow.xaml(.cs) # 进度窗口 │ └── ViewModels/UpdateViewModel.cs # 进度与状态绑定 │ ├── BlackGoldAncientSword.Downloader/ # 离线安装包下载器(WinExe,独立单文件) │ ├── App.xaml(.cs) # 入口,进程级兜底清理临时目录 │ ├── Services/ │ │ ├── DownloaderRunner.cs # 编排:查 Gitee latest → 顺序流式下载分卷 → 拉起 Setup │ │ ├── GiteeAssetsFetcher.cs # 走 302 + CDN,零 Gitee API 依赖(避 rate limit) │ │ └── InstallerForegrounder.cs # 拉起主 Setup exe 并前台化 │ ├── Shell/DownloadWindow.xaml(.cs) # 下载进度窗口(进度 + 4-stat 实时刷新) │ └── ViewModels/DownloadViewModel.cs │ ├── BlackGoldAncientSword.Framework/ # 核心框架 │ ├── Core/ │ │ ├── Attributes/ # ComponentAttribute(DI 自动注册标记) │ │ ├── Bases/ # ViewModelBase、PrismApplicationBase 等 │ │ ├── Consts/ # GlobalConstant、PageNames │ │ ├── Events/ # GameStatusChanged、SettingsChanged、TipMessageEvent │ │ ├── Extensions/ # 扩展方法与 Value Converter │ │ └── Infrastructure/ # IMainContentNavigationService / MainContentNavigator │ ├── Http/ │ │ ├── Definitions/ │ │ │ ├── api-definitions.json # API 端点 / 请求 / 响应定义(→ 源码生成) │ │ │ └── enums.json # 枚举定义 │ │ └── JsonFlexibleStringConverter.cs # System.Text.Json 容错转换器 │ ├── Services/ │ │ ├── Abstractions/ # 13 个服务接口(见下表) │ │ └── Implementation/ # 服务实现 │ ├── Themes/Generic.xaml # HandyControl 主题 │ └── UI/Controls/ # 自定义 WPF 控件(DataGridWrapPanel 等) │ ├── BlackGoldAncientSword.Framework.SourceGenerator/ # Roslyn 源码生成器 │ ├── ApiDefinitionsParser.cs # 解析 api-definitions.json │ ├── EnumSourceGenerator.cs # 生成枚举类型 │ ├── HttpApiSourceGenerator.cs # 生成 NarakaApiClient + DTO(Client 模式) │ └── HttpApiTestSourceGenerator.cs # 生成 HTTP API 测试代码(Tests 模式) │ ├── BlackGoldAncientSword.Modules/ # UI 页面模块(10 个 Prism IModule) │ ├── Mappings/BattleMappingRegister.cs # Mapster 映射注册 │ ├── Module/ # 10 个 IModule 注册 │ │ ├── AnnouncementModule.cs # 公告 │ │ ├── BattleDetailModule.cs # 对局详情浮层(personal/team/top5 三 Tab) │ │ ├── ClosePromptModule.cs # 关闭确认弹窗 │ │ ├── FeedbackModule.cs # 意见反馈 │ │ ├── HomeModule.cs # 首页(游戏状态监控) │ │ ├── SearchModule.cs # 搜索历史 │ │ ├── SettingsModule.cs # 设置 │ │ ├── StatsModule.cs # 战绩查询 │ │ ├── TeamInfoModule.cs # 队伍信息(OCR + 对比) │ │ └── UpdateNotificationModule.cs # 新版本提示 / 启动更新器 │ └── UI/ # 各模块的 ViewModels + Views │ ├── BattleDetail/ # 对局详情:并行拉 personal/team/top5 │ ├── Stats/Services/ # 战绩聚合服务 │ ├── TeamInfo/Services/ # TeamInfoOcrService、TeamOcrCoordinator │ └── UpdateNotification/ViewModels/ # 拉起 BlackGoldAncientSword.Update.exe │ ├── BlackGoldAncientSword.GameMonitor/ # 游戏监控 │ ├── Models/ # BattleEventArgs、PlayerPrefsData │ ├── Services/ │ │ ├── Abstractions/ # IGameLogMonitor / IGameStatusMonitor / IPlayerPrefsService │ │ └── Implementation/ │ │ ├── GameLogMonitor.cs # facade(编排生命周期与事件分发) │ │ ├── GameStatusMonitor.cs # 游戏状态状态机 │ │ ├── PlayerPrefsService.cs # 本地用户偏好 │ │ └── Internal/ │ │ ├── BattleStateMachine.cs # 战局状态机 │ │ ├── LogPoller.cs # 轮询循环 │ │ └── LogReader.cs # Player.log 读取 │ └── GameMonitorAutoRegister.cs # 服务自动注册 │ ├── BlackGoldAncientSword.ScreenCapture/ # 屏幕捕获(Windows Graphics Capture API) │ ├── IScreenCaptureService.cs # 服务接口 │ ├── ScreenCaptureService.cs # WGC 封装 │ ├── NativeWgc.cs / WgcInterop.cs # 原生 WGC API 互操作 │ ├── ScreenQuadrant.cs # 屏幕四象限分割 │ ├── native/ # 原生 C++ 源码与构建脚本 │ └── runtimes/win-x64/native/ │ └── wgc_capture.dll # 原生 C++/WinRT 捕获库 │ ├── BlackGoldAncientSword.Ocr/ # OCR 引擎(进程内 ONNX Runtime) │ ├── IOcrService.cs # 服务接口 │ ├── OcrEngine.cs # RapidOcrNet(PP-OCRv5)封装 │ └── OcrAutoRegister.cs # 服务自动注册 │ ├── BlackGoldAncientSword.Resources/ # 多语言资源 │ ├── Images/ # UI 图片、应用图标 (app.ico) │ └── Themes/ │ ├── Strings.zh-CN.xaml # 简体中文 │ ├── Strings.en.xaml # English │ └── Strings.zh-TW.xaml # 繁體中文 │ └── BlackGoldAncientSword.Tests/ # 测试项目(xUnit + Moq) ├── GameMonitor/ # 游戏监控测试 ├── Http/ # HTTP / JSON 容错测试(部分代码由源码生成器产出) ├── Ocr/ # OCR 测试 ├── ScreenCapture/ # 屏幕捕获测试 ├── Update/ # 更新流程测试 └── TestData/ # 测试数据 ocr_engine/ # PP-OCRv5 ONNX 模型与字典(被 Ocr 项目拷贝至输出目录) └── models/v5/ # PP-OCRv5 中文 mobile 模型 (~22MB) ├── ch_PP-OCRv5_det_mobile.onnx # 文本检测 DBNet ├── ch_PP-LCNet_x0_25_textline_ori_cls_mobile.onnx # 方向分类 ├── ch_PP-OCRv5_rec_mobile.onnx # 字符识别 CRNN └── ppocrv5_dict.txt # 字典(18383 字符,覆盖中/英/日/拉丁扩展等)Framework 服务接口一览
BlackGoldAncientSword.Framework/Services/Abstractions/下共 13 个公开接口:
| 接口 | 主要实现 | 用途 |
|---|---|---|
IAppAssemblyMarker | AppAssemblyMarker | 程序集定位标记(XAML 资源解析) |
IApplicationLifetime | WpfApplicationLifetime | 退出 / 重启应用 |
IClipboardService | WpfClipboardService | 剪贴板读写 |
IGiteeReleaseService | GiteeReleaseService | 拉取 Gitee Releases 列表与资产(含 302 tag 探测 + CDN 分卷 HEAD 探测,零 API 依赖) |
IImageCacheService | ImageCacheService | 图片磁盘缓存 |
ILocalizationService | LocalizationService | 动态切换语言(重载 XAML 资源字典) |
ILocalizedTextProvider | WpfLocalizedTextProvider | 代码侧读取本地化字符串 |
ISearchHistoryService | SearchHistoryService | 搜索历史持久化 |
ISettingsService | SettingsService | 应用配置读写 |
ITeamOverlayService | TeamOverlayService | 英雄选择时的右下角队伍弹窗 |
ITipMessageService | TipMessageService | 全局 Toast / 提示消息 |
IUIDispatcher | WpfUIDispatcher | 跨线程 UI 调度封装 |
IUpdateService | UpdateService | 比对版本、解析最新 Gitee release 的 Setup / zip / 分卷 URL(走 302 + CDN,避 API rate limit) |
GameMonitor、Ocr、ScreenCapture各自暴露自身的接口(IGameLogMonitor/IGameStatusMonitor/IPlayerPrefsService、IOcrService、IScreenCaptureService),通过各模块的*AutoRegister.cs注册到 DI 容器。
核心模块说明
1. MVVM 架构(Prism + DryIoc)
- 所有 ViewModel 继承自
ViewModelBase,提供RaisePropertyChanged()方法(遵循 CLAUDE.md / AGENTS.md 规范,禁止SetProperty封装) - 属性变更通知使用
nameof()或[CallerMemberName],禁止硬编码属性名字符串 - ViewModel 中禁止引用 WPF 类型(
Visibility、Brush、Color等);可见性用bool+ Converter 表达 - 页面通过
IMainContentNavigationService进行导航,支持前进 / 后退 - 跨模块通信使用
IEventAggregator发布 / 订阅事件(如TipMessageEvent、SettingsChangedEvent)
2. 模块化按需加载
9 个 UI 页面分别是一个 PrismIModule,在ModuleCatalogConfigManager中配置为OnDemand:首次导航到某页面时才加载对应模块,减少启动时间。
// PageNames.cspublicstaticclassPageNames{publicconststringHomePage=nameof(HomePage);publicconststringStatsPage=nameof(StatsPage);publicconststringSearchPage=nameof(SearchPage);publicconststringTeamInfoPage=nameof(TeamInfoPage);publicconststringSettingsPage=nameof(SettingsPage);publicconststringAnnouncementPage=nameof(AnnouncementPage);publicconststringClosePromptPage=nameof(ClosePromptPage);publicconststringFeedbackPage=nameof(FeedbackPage);publicconststringUpdateNotificationPage=nameof(UpdateNotificationPage);publicconststringBattleDetailPage=nameof(BattleDetailPage);}3. 游戏状态监控(GameMonitor)
GameLogMonitor采用FileSystemWatcher + 定时轮询双保险监听 Player.log 文件变更。内部将职责拆分为:
LogReader(文件读取)LogPoller(轮询循环)BattleStateMachine(战局状态机)
外层GameLogMonitor仅作为 facade 编排生命周期与事件分发。监测到的事件:
BattleJoined— 进入英雄选择(解析日志中的 RoomId)BattleStarted— 对局开始(解析 BattleId)BattleEnded— 对局结束
GameStatusMonitor维护游戏状态机,通知各页面当前处于哪个阶段(HeroSelection/InGame/BattleEnded)。HomePageViewModel额外使用Process.GetProcessesByName("NarakaBladepoint")检测进程是否存在,作为辅助判断。
4. 屏幕捕获与 OCR(队伍信息识别)
队伍信息识别流程:
GameStatusMonitor检测到HeroSelection状态TeamInfoPageViewModel启动 OCR 轮询循环ScreenCaptureService通过Windows Graphics Capture API(原生 C++/WinRT DLL → SharpDX D3D11)截取游戏窗口,使用ArrayPool复用全帧缓冲,按ScreenQuadrant切出三个 region 拼图OcrEngine基于RapidOcrNet + ONNX Runtime 进程内推理:byte[] → SkiaSharp 解码为SKBitmap→ 单次Detect()串联跑 det(DBNet)→ cls(方向分类,可关)→ rec(CRNN)三段 ONNX 推理。模型 + 字典首次调用PrewarmAsync时加载(约 200~500 ms),并跑一次最小推理触发 ONNX session 内部 buffer 与 kernel 编译。SemaphoreSlim串行化保护 RapidOcr 内部状态,无子进程 / 无 IPC / 无 JobObject 兜底TeamInfoOcrService/TeamOcrCoordinator解析 OCR 结果,提取队友昵称- 调用战绩 API 查询每个队友的数据,并排展示
5. HTTP API 源码生成
API 客户端不手写,而是通过BlackGoldAncientSword.Framework.SourceGenerator在编译期从Http/Definitions/*.json自动生成:
- JSON 定义文件描述 API 的端点、请求 / 响应数据结构与枚举
- 生成器以Roslyn Source Generator形式工作,被 Framework / Tests 两端以 Analyzer 引用
- 通过
BgaSourceGenMode属性切换产物:Client模式(Framework)— 生成NarakaApiClient+ DTOTests模式(Tests)— 生成 HTTP API 测试代码
6. 多语言支持
多语言通过 WPFResourceDictionary实现,所有 UI 文本定义在Strings.{zh-CN,en,zh-TW}.xaml中。运行时通过ILocalizationService.ApplyLanguage()动态切换资源字典,无需重启。
7. 在线更新(独立 Updater 进程)
更新由两端协作完成:
- 主程序侧(
Modules/UI/UpdateNotification/ViewModels/UpdateNotificationPageViewModel.cs)- 通过
IUpdateService(走 Gitee release 网页 302 提取 tag + CDN HEAD 探测分卷)检测新版本 - 用户点击"在线更新"后,启动同目录下的
BlackGoldAncientSword.Update.exe,传入--url <zip 下载地址>、--target <安装目录>、--main-exe BlackGoldAncientSword.App.exe - 无网 / GitHub 被墙用户可从 Gitee Release 页面下载
BlackGoldAncientSword-win-x64-Downloader.exe(离线下载器),双击后自动流式拉取分卷安装包并调起 Setup
- 通过
- 更新器侧(
BlackGoldAncientSword.Update)- 独立进程,不引用任何业务项目(仅依赖 HandyControl),避免 DLL 被锁定影响整目录覆盖
UpdaterRunner编排:下载 zip(0–90%)→ 解压(90–98%)→ 提示关闭主程序 → 全量覆盖 → 重新拉起主程序 → 自身退出- 以 self-contained +
PublishSingleFile+EnableCompressionInSingleFile发布
构建与运行
环境要求
- Windows 10/11 x64
- .NET 10.0 SDK
- PowerShell 7+(推荐,UTF-8 环境)
构建命令
# 还原 + 编译整个解决方案dotnet build src/BlackGoldAncientSword.slnx# 仅编译主程序dotnet build src/BlackGoldAncientSword.App/BlackGoldAncientSword.App.csproj-c Debug# Release 发布主程序(自包含单文件 exe)dotnet publish src/BlackGoldAncientSword.App/BlackGoldAncientSword.App.csproj-c Release-o publish/App# Release 发布更新器(自包含单文件 exe,需与主程序放同目录)dotnet publish src/BlackGoldAncientSword.Update/BlackGoldAncientSword.Update.csproj-c Release-o publish/Updater# Release 发布离线下载器(自包含单文件 exe,作为 Release 独立附件发布,不进主程序安装目录)dotnet publish src/BlackGoldAncientSword.Downloader/BlackGoldAncientSword.Downloader.csproj-c Release-o publish/Downloader项目约定:对代码做任何修改后必须运行
dotnet build src/BlackGoldAncientSword.slnx,0 error 才算完成。
运行测试
dotnet test src/BlackGoldAncientSword.Tests/BlackGoldAncientSword.Tests.csprojCI / 发布流程
.github/workflows/下共两个工作流:
| 工作流 | 触发 | 用途 |
|---|---|---|
main-build.yml | push / PR →main | 校验性构建(dotnet build src/BlackGoldAncientSword.slnx),不发布 |
dotnet-desktop.yml | push →release | 完整发版:版本号自增 → 编译 App → 发布 App + Updater + Downloader(自包含单文件)→ 打包 zip + Inno Setup 全量 / 分卷安装包 → 创建 GitHub Release |
发版流程要点:
- 从已有 git tags(
v*.*.*.*形式)推断版本号并自增 build 段 - 修改
App.csproj的Version/AssemblyVersion/FileVersion - 分别发布 App、Update、Downloader 为自包含单文件 .exe
- 合并 build + publish 输出并把 Updater exe 一并塞进安装目录 → 压缩为
BlackGoldAncientSword-v{version}.zip+ 7z 分卷-split.zip.NNN(≤99MB / 卷) - 用
setup.iss(Inno Setup 脚本)分别生成全量安装包BlackGoldAncientSword-{version}-win-x64-Setup.exe与 DiskSpanning 分卷安装包-Split.exe+.bin - 额外产出两份无版本号别名(
BlackGoldAncientSword-win-x64-Setup.exe/-Downloader.exe),配合/releases/latest/download/magic redirect 提供永久指向最新版的分享链接 - 创建 GitHub Release,自动列举上一版本到本次的 commit 标题
release分支已开启分支保护:禁直推 / 禁 force-push / 禁删除,且对管理员同样生效(enforce_admins),所有变更必须通过 PR 合并进来。日常开发在main分支进行;发版时先由 git-commit skill commit + pushmain,随后在 GitHub 上创建main→release的 PR 并合并,由此触发dotnet-desktop.yml完成发版。
许可证
本项目基于 MIT License 开源。作者:小窗同学。
