黑金古刀-永劫助手(BlackGoldAncientSword)——《永劫无间》战绩查询与队友识别桌面工具

📅 2026/7/4 4:21:49 👁️ 阅读次数 📝 编程学习
黑金古刀-永劫助手(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

> 可点击"重新识别"按钮手动触发一轮 OCR。若识别到的文字有误,可直接修改后重新查询。

设置

设置页面集中管理应用配置:

  • 数据保存路径:战绩数据的本地存储目录(支持自定义 + 旧数据自动迁移)
  • 缓存路径:图片缓存目录(含缓存大小显示与一键清理)
  • 语言:支持 简体中文 / English / 繁體中文
  • 关闭行为:点击关闭按钮时的默认行为,可选"每次询问 / 最小化到任务栏 / 最小化到系统托盘 / 直接退出",并支持记住选项
  • 英雄选择时的右下角队伍提示弹窗:开关控制
  • 检查更新:手动检查与下载新版本(调用独立的 Update 程序在线更新,详见下文)
  • 当前版本:显示版本号


设置


在线更新

助手在启动时和"设置 → 检查更新"中均会自动比对 GitHub Releases 的最新版本。检测到新版本时会弹出更新提示页面,点击"在线更新"即可:

  1. 主程序拉起独立的BlackGoldAncientSword.Update.exe(更新器)并传入下载地址、安装目录、主程序文件名等参数;
  2. 更新器下载新版 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.AppWinExeWPF 应用入口、主窗口、侧边栏导航、托盘、启动更新器、启动期后台预热 OCR
更新器BlackGoldAncientSword.UpdateWinExe独立在线更新进程,零业务依赖(仅 HandyControl)
离线下载器BlackGoldAncientSword.DownloaderWinExe独立单文件 exe,从 Gitee release 顺序流式下载分卷安装包 → 拉起 Setup.exe → 自身退出。零 API 依赖(走 302 + CDN)
UI 模块BlackGoldAncientSword.ModulesClassLib10 个 PrismIModule页面,按需加载
核心框架BlackGoldAncientSword.FrameworkClassLibMVVM 基类、Prism 基础设施、服务抽象与实现、HTTP API
游戏监控BlackGoldAncientSword.GameMonitorClassLib进程检测、Player.log 解析、战局状态机
屏幕捕获BlackGoldAncientSword.ScreenCaptureClassLibWindows Graphics Capture API + SharpDX,含原生 wgc_capture.dll
OCR 引擎BlackGoldAncientSword.OcrClassLibRapidOcrNet(PP-OCRv5 ONNX)进程内推理封装
资源BlackGoldAncientSword.ResourcesClassLib多语言 XAML 资源字典、图标、图片
源码生成BlackGoldAncientSword.Framework.SourceGeneratorRoslyn Analyzer编译期从 JSON 定义生成 HTTP 客户端与测试代码
测试BlackGoldAncientSword.TestsxUnitOCR、屏幕捕获、游戏监控、HTTP、更新流程测试

技术栈

类别技术 / 库用途
运行时.NET 10.0 (net10.0-windows)目标框架
UIWPF + HandyControl 3.5桌面界面与控件库
主题自定义 ModernTheme(青瓷竹青护眼配色)淡雅护眼浅绿底 + 竹青深绿点缀 + 深墨字,长时间阅读舒适
MVVM 框架Prism 8.1 (Prism.DryIoc)DI 容器、区域导航、模块化
HTTP编译期源码生成器api-definitions.json自动生成强类型 API 客户端
对象映射Mapster 7.4DTO ↔ ViewModel
JSONSystem.Text.Json(含源码生成上下文)序列化 / 反序列化(已全量替换 Newtonsoft.Json)
屏幕捕获SharpDX.Direct3D11 + 原生 WGC DLL (C++/WinRT)游戏窗口截图
OCRRapidOcrNet 2.0.0 + ONNX Runtime 1.24(进程内推理,PP-OCRv5 模型)多语言文字识别(中/英/日/拉丁/西里尔等单模型覆盖)
图像处理SkiaSharp 3.119OCR 入口 byte[] → SKBitmap 解码
系统托盘Hardcodet.NotifyIcon.Wpf托盘图标与菜单
测试xUnit + Moq单元测试与集成测试
打包Self-Contained + PublishSingleFileApp、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 个公开接口:

接口主要实现用途
IAppAssemblyMarkerAppAssemblyMarker程序集定位标记(XAML 资源解析)
IApplicationLifetimeWpfApplicationLifetime退出 / 重启应用
IClipboardServiceWpfClipboardService剪贴板读写
IGiteeReleaseServiceGiteeReleaseService拉取 Gitee Releases 列表与资产(含 302 tag 探测 + CDN 分卷 HEAD 探测,零 API 依赖)
IImageCacheServiceImageCacheService图片磁盘缓存
ILocalizationServiceLocalizationService动态切换语言(重载 XAML 资源字典)
ILocalizedTextProviderWpfLocalizedTextProvider代码侧读取本地化字符串
ISearchHistoryServiceSearchHistoryService搜索历史持久化
ISettingsServiceSettingsService应用配置读写
ITeamOverlayServiceTeamOverlayService英雄选择时的右下角队伍弹窗
ITipMessageServiceTipMessageService全局 Toast / 提示消息
IUIDispatcherWpfUIDispatcher跨线程 UI 调度封装
IUpdateServiceUpdateService比对版本、解析最新 Gitee release 的 Setup / zip / 分卷 URL(走 302 + CDN,避 API rate limit)

GameMonitorOcrScreenCapture各自暴露自身的接口(IGameLogMonitor/IGameStatusMonitor/IPlayerPrefsServiceIOcrServiceIScreenCaptureService),通过各模块的*AutoRegister.cs注册到 DI 容器。


核心模块说明

1. MVVM 架构(Prism + DryIoc)

  • 所有 ViewModel 继承自ViewModelBase,提供RaisePropertyChanged()方法(遵循 CLAUDE.md / AGENTS.md 规范,禁止SetProperty封装)
  • 属性变更通知使用nameof()[CallerMemberName],禁止硬编码属性名字符串
  • ViewModel 中禁止引用 WPF 类型VisibilityBrushColor等);可见性用bool+ Converter 表达
  • 页面通过IMainContentNavigationService进行导航,支持前进 / 后退
  • 跨模块通信使用IEventAggregator发布 / 订阅事件(如TipMessageEventSettingsChangedEvent

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(队伍信息识别)

队伍信息识别流程:

  1. GameStatusMonitor检测到HeroSelection状态
  2. TeamInfoPageViewModel启动 OCR 轮询循环
  3. ScreenCaptureService通过Windows Graphics Capture API(原生 C++/WinRT DLL → SharpDX D3D11)截取游戏窗口,使用ArrayPool复用全帧缓冲,按ScreenQuadrant切出三个 region 拼图
  4. 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 兜底
  5. TeamInfoOcrService/TeamOcrCoordinator解析 OCR 结果,提取队友昵称
  6. 调用战绩 API 查询每个队友的数据,并排展示

5. HTTP API 源码生成

API 客户端不手写,而是通过BlackGoldAncientSword.Framework.SourceGenerator在编译期从Http/Definitions/*.json自动生成:

  • JSON 定义文件描述 API 的端点、请求 / 响应数据结构与枚举
  • 生成器以Roslyn Source Generator形式工作,被 Framework / Tests 两端以 Analyzer 引用
  • 通过BgaSourceGenMode属性切换产物:
    • Client模式(Framework)— 生成NarakaApiClient+ DTO
    • Tests模式(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.csproj

CI / 发布流程

.github/workflows/下共两个工作流:

工作流触发用途
main-build.ymlpush / PR →main校验性构建(dotnet build src/BlackGoldAncientSword.slnx),不发布
dotnet-desktop.ymlpush →release完整发版:版本号自增 → 编译 App → 发布 App + Updater + Downloader(自包含单文件)→ 打包 zip + Inno Setup 全量 / 分卷安装包 → 创建 GitHub Release

发版流程要点:

  1. 从已有 git tags(v*.*.*.*形式)推断版本号并自增 build 段
  2. 修改App.csprojVersion/AssemblyVersion/FileVersion
  3. 分别发布 App、Update、Downloader 为自包含单文件 .exe
  4. 合并 build + publish 输出并把 Updater exe 一并塞进安装目录 → 压缩为BlackGoldAncientSword-v{version}.zip+ 7z 分卷-split.zip.NNN(≤99MB / 卷)
  5. setup.iss(Inno Setup 脚本)分别生成全量安装包BlackGoldAncientSword-{version}-win-x64-Setup.exe与 DiskSpanning 分卷安装包-Split.exe+.bin
  6. 额外产出两份无版本号别名(BlackGoldAncientSword-win-x64-Setup.exe/-Downloader.exe),配合/releases/latest/download/magic redirect 提供永久指向最新版的分享链接
  7. 创建 GitHub Release,自动列举上一版本到本次的 commit 标题

release分支已开启分支保护:禁直推 / 禁 force-push / 禁删除,且对管理员同样生效(enforce_admins),所有变更必须通过 PR 合并进来。日常开发在main分支进行;发版时先由 git-commit skill commit + pushmain,随后在 GitHub 上创建mainrelease的 PR 并合并,由此触发dotnet-desktop.yml完成发版。

许可证

本项目基于 MIT License 开源。作者:小窗同学