diff --git a/.gitignore b/.gitignore index f5b4499..cbf13f8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,6 @@ data/ dist/ **/dist-newstyle/ go/.cache/ -go/bd2server.exe -go/bd2server -go/*.test go/coverage.out *.prof *.pprof @@ -33,7 +30,6 @@ TestResults/ .ghc.environment.* # Python caches and temporary files -tools/python/repair/ __pycache__/ **/__pycache__/ *.py[cod] diff --git a/README.md b/README.md index eb36410..3f0a00e 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,6 @@ ## 开发构建 -```powershell -# Go -Push-Location .\go -go test ./... -go build .\cmd\bd2server -go build .\cmd\bd2client -Pop-Location -``` - 开发时在两个终端中分别从 `go` 目录运行: ```powershell @@ -25,15 +16,9 @@ go run .\cmd\bd2server --dev run go run .\cmd\bd2client --dev run ``` -服务端开发入口会自动使用仓库根目录的版本、认证、资源、数据和存档配置;客户端开发入口会直接使用仓库版本清单和插件产物,并从本机开发配置读取游戏目录,随后用 SDK 内嵌的当前版本名字表增量构建两个客户端插件,无需提供官方映射文件。首次开发前创建该配置: +客户端窗口在插件准备完成后打开。首次生成完整游戏源码或者在 SDK / 游戏更新后可能等待数分钟,后续启动复用共享缓存。 -客户端窗口在插件准备完成后打开。首次生成完整游戏源码或 SDK/游戏更新后可能等待数分钟,终端会实时显示构建和反编译进度;后续启动复用共享缓存。 - -```powershell -Copy-Item .\go\config.example.json .\go\config.json -``` - -编辑 `go/config.json`,将 `game_directory` 改为本机 Brown Dust II 安装目录。仍可在 `run` 后使用 `--game-dir` 临时覆盖;显式参数的优先级高于开发配置。 +将 `go\config.example.json` 重命名为 `confg.json`,将 `game_directory` 改为本机 Brown Dust II 安装目录。仍可在 `run` 后使用 `--game-dir` 临时覆盖。 发布脚本统一使用 `-tags release` 编译。 @@ -43,19 +28,21 @@ Copy-Item .\go\config.example.json .\go\config.json .\build-release.ps1 ``` -脚本在 Windows 本机构建版本化归档,例如 `.build\bd2server-2.35.10+server.0.1.0-windows-x64.zip` 和 `.build\bd2client-2.35.10+client.0.1.0-windows-x64.zip`。纯服务端包只包含 `bd2server.exe`、seed、认证/资源策略、游戏规则配置和服务端数据目录;客户端包只包含 `bd2client.exe`、客户端插件和版本文件。 +脚本只适用于 Windows ,输出在 `.build\bd2server-{gameversion}+server.{serverversion}-windows-x64.zip` 和 `.build\bd2client-{gameversion}+client.{clientversion}-windows-x64.zip`。 -macOS 客户端使用系统 Cocoa / WKWebView,需要 macOS 原生构建环境。本地 Windows 发布脚本不会交叉编译或生成 macOS 发布包;找到 macOS 测试者或准备公开发布时,再通过 GitHub Actions 的 macOS runner 完成原生构建、测试及 `.app` 打包。签名和公证也应在该流程中配置。 +macOS/Linux 需自行编写所需脚本。 ## 客户端插件项目 - `plugins/LocalIdentity/`:本地服务端客户端专用插件。 - `plugins/LoginUI/`:本地服 Discord/Google 登录界面插件。 +- `plugins/CashShop`: 内购商品处理。 - `plugins/CaptureEnvironment/`:独立原版对照客户端的抓包插件,不要装进本地服务端客户端。 +- `plugins/GameNames`/`plugins/GameSdk`: 插件开发工具链,让开发过程中使用反混淆名改善开发体验,只有 `GameNames` 需要随同安装。 ## 可视化客户端工具 -BD2 Client Studio 是使用 Wails 的独立桌面客户端设置工具。Windows 使用系统 WebView2 Runtime,macOS 使用系统 WKWebView;应用自己管理窗口和退出,原生窗口关闭后整个客户端进程会退出。它提供以下操作: +BD2 Client Studio 是使用 Wails 的独立桌面客户端设置工具。Windows 使用系统 WebView2 Runtime,macOS 使用系统 WKWebView。它提供以下操作: - 选择并验证 Brown Dust II 安装目录。 - 填写服务器 origin 和端口,自动写入游戏目录下的 `BepInEx/config/bd2.client.json`。 @@ -71,14 +58,11 @@ BD2 Client Studio 是使用 Wails 的独立桌面客户端设置工具。Windows 双击 `bd2server.exe` 启动,单人本地服默认监听 `8080` 端口,可通过 `.\bd2server.exe serve --listen 127.0.0.1:xxxx` 修改监听端口。 -服主部署、创建 OAuth 应用、取得 client ID/secret、配置回调地址和安全注入环境变量的完整步骤见 [服主配置指南](AUTHENTICATION.md)。 - - -认证策略由 `bd2server.exe` 同目录的 `authentication.json` 权威决定。`mode=local`(默认)不依赖第三方登录,单人本地服保持不动,联机服可设为 `oauth` 来让玩家通过 Discord/Google 登录。 +服主部署、创建 OAuth 应用、取得 client ID/secret、配置回调地址等完整步骤见 [服主配置指南](AUTHENTICATION.md)。 `authentication.json`、`resources.json` 和 `game.json` 不随发布包分发,首次运行时在服务端可执行文件旁生成默认文件,已有文件不会覆盖。开发入口使用 `.build/config/` 中的三个配置。游戏规则修改后重启生效,详细见 [服务端游戏规则配置](GAME_CONFIGURATION.md)。 -服务端日志默认输出 INFO 及以上级别,仅终端启用颜色:TRACE 灰、DEBUG 青、INFO 绿、WARN 黄、ERROR 红。可用 `serve --log-level debug --log-color auto` 调整,或设置 `BD2_LOG_LEVEL` 和 `BD2_LOG_COLOR` 环境变量;显式命令行参数优先。级别支持 `trace/debug/info/warn/error`,颜色支持 `auto/always/never`。`auto` 下文件和重定向保持纯文本,`NO_COLOR` 或 `TERM=dumb` 也会关闭颜色;如需在 Docker 日志流中显示颜色,可显式选择 `always`。 +服务端日志默认输出 INFO 及以上级别,仅终端启用颜色:TRACE 灰、DEBUG 青、INFO 绿、WARN 黄、ERROR 红。可用 `serve --log-level debug --log-color auto` 调整,或设置 `BD2_LOG_LEVEL` 和 `BD2_LOG_COLOR` 环境变量,显式命令行参数优先。级别支持 `trace/debug/info/warn/error`,颜色支持 `auto/always/never`。`auto` 下文件和重定向保持纯文本,`NO_COLOR` 或 `TERM=dumb` 也会关闭颜色;如需在 Docker 日志流中显示颜色,可显式选择 `always`。 ### 启动客户端 @@ -89,6 +73,6 @@ BD2 Client Studio 是使用 Wails 的独立桌面客户端设置工具。Windows ## 许可与免责声明 -本项目原创内容由 Flechazo 保留全部权利,具体中英双语条款见 [LICENSE](LICENSE)。通过项目权利人指定渠道合法取得副本的人,仅可用于个人学习、研究和本地非商业测试;未经项目权利人事先明确书面许可,禁止向第三方转发、镜像、上传、二次分发项目源码或构建产物,禁止售卖、收费提供、商业化运营或对公众开放基于本项目的服务。公开可见不代表允许转载或再分发。 +本项目原创内容由 Flechazo 保留全部权利,具体条款见 [LICENSE](LICENSE)。通过项目权利人指定渠道合法取得副本的人,仅可用于个人学习、研究和本地非商业测试;未经项目权利人事先明确书面许可,禁止向第三方转发、镜像、上传、二次分发项目源码或构建产物,禁止售卖、收费提供、商业化运营或对公众开放基于本项目的服务。公开可见不代表允许转载或再分发。 本项目是非官方开发与研究项目,与 Brown Dust II 及其权利人无隶属或授权关系。游戏名称、商标、客户端、游戏资源和数据归各自权利人所有;本项目的许可不覆盖它们,也不变更第三方依赖的许可证。项目按现状提供,无正确性、安全性、可用性或不侵权保证。使用者须自行确认适用法律、相关协议和第三方权利要求,并自行承担使用、客户端修改及本地服务运行风险。 diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 6b9b330..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,41 +0,0 @@ -# BD2 纯服务端发布包 - -## 首次使用 - -1. 准备服务端数据目录。服务端不需要 Windows 游戏客户端、BepInEx 或客户端插件。 -2. 编辑同目录的 `authentication.json`、`resources.json`;OAuth 配置见 `AUTHENTICATION.md`。 -3. 启动服务器: - - Windows PowerShell: - - ```powershell - .\bd2server.exe serve - ``` - - macOS/Linux(Bash 或 Zsh): - - ```bash - ./bd2server serve - ``` - -服务端默认使用可执行文件旁的 `data` 目录,玩家存档位于 `data/state/state.db`,服务端逻辑所需 GameData 位于 `data/resources/GameData`。缺失时会从官方源下载并完整校验。服务端不会访问或修改玩家客户端目录。 - -4. 确认健康检查成功: - - ```bash - curl --fail --silent --show-error http://127.0.0.1:8080/readyz - ``` - -5. 让玩家使用独立的 `bd2client.exe` 选择游戏目录、填写服务器地址、选择 CDN,并安装 `BD2LocalIdentity.dll`、`BD2LoginUI.dll` 与 `BD2CashShop.dll`。客户端工具说明见 `README.md`(客户端包)或仓库的 `docs/CLIENT.md`。 - -`versions.json` 是服务端和客户端插件共用的版本选择,必须与各自可执行文件保持在同一目录。`game_version` 锁定官方游戏兼容版本;`client_version` 与 `server_version` 分别标识客户端工具和纯服务端发布版本,并以 `游戏版本+组件.X.Y.Z` 组合。服务端从包内 `go/seed` 读取种子,不依赖当前工作目录。需要临时测试另一组版本时可传 `serve --version-config <文件>`。玩家存档位于 `data\state\state.db`;服务端以 Go 迁移器按相邻版本升级,并在同一个 SQLite 事务内完成迁移和最终校验,失败时不会留下部分升级。 - -`authentication.json` 和 `resources.json` 必须与 `bd2server.exe` 保持在同一目录。默认 `local` 认证模式继续自动本地登录;公网或联机服可以启用 OAuth,并把资源策略设为官方 CDN 或统一的服务器资源源。服主自建与反代使用相同的 `server` 模式;玩家本地资源目录仅由 `bd2client.exe` 配置。逐步配置方法见发布包内的 [服主第三方登录配置指南](AUTHENTICATION.md) 和 [服主资源与 CDN 配置指南](RESOURCES.md)。 - -游戏规则使用同目录的 `game.json`,修改后重启服务端生效。默认关闭联动 UR 专武扩展;需要将 14 种联动角色专武加入 UR 必得装备券池时,按 [服务端游戏规则配置](GAME_CONFIGURATION.md) 设置。升级时保留已修改的文件;旧安装缺少文件时使用默认规则。 - -排期由项目维护,存放在 `bd2server.exe` 同目录的 `schedules/` 中,使用真正的自定义二进制格式 `.bd2schedule`。服务端启动时读取其中所有排期文件并统一下发。完整服务端包包含同一套排期;排期文件也可以单独分发,无需更新服务端可执行文件。排期更新时停止服务端,用发布的排期文件完整替换旧 `schedules/` 目录,再启动服务端,避免遗留旧文件继续生效。排期文件只适用于发布目录名称标明的游戏版本。 - -维护者仅发布排期时,在仓库根目录运行 `./build-release.ps1 -SchedulesOnly`,独立文件输出到 `.build/bd2schedules-<游戏版本>-<内容哈希>/`,无需打包 ZIP。此命令无需游戏客户端目录,也不会构建服务端、客户端或插件。服主直接安装项目发布的排期文件。格式与维护说明见 [排期数据说明](docs/SCHEDULES.md)。 - -OAuth access token 只在客户端内存中;Windows refresh credential 使用当前用户 DPAPI 加密后写入 PlayerPrefs 注册表,macOS 使用 Keychain Services。服务端 `auth.db` 只保存 token、device secret、OAuth state 及 provider subject 的 HMAC,临时可恢复材料使用 AES-256-GCM。 diff --git a/RESOURCES.md b/RESOURCES.md index f5f2890..7b05425 100644 --- a/RESOURCES.md +++ b/RESOURCES.md @@ -1,18 +1,16 @@ # 服主资源与 CDN 配置指南 -`bd2server` 不要求 Windows 游戏目录,也不要求玩家的本地 ServerData 目录。服务端只会自动准备自身逻辑需要的 GameData。玩家在 `bd2client` 中有三种资源来源: +`bd2server` 服务端只会自动准备自身逻辑需要的 GameData。玩家在 `bd2client` 中有三种资源来源: - **官方 CDN**:玩家直接从官方节点下载。 -- **服务器资源源**:客户端向游戏服务器查询资源 URL;服主可以在 URL 后部署自建镜像或官方 CDN 反代,两者使用同一种协议。 -- **本地资源目录**:客户端使用玩家已经下载的资源;目录选择和校验完全发生在玩家设备上。 +- **服务器资源源**:客户端向游戏服务器查询资源 URL;服主可以在 URL 后部署自建镜像或官方 CDN 反代都可,两者使用同一种协议。 +- **本地资源目录**:客户端使用玩家已经下载的资源。 无论怎样,最终的资源都是要来到玩家的客户端的。 -`resources.json` 只配置 `official` 或 `server`。服务端不会接收、保存或返回玩家的本地资源路径。 +## 小服与 FRP -## 朋友小服与 FRP - -推荐在 `resources.json` 中使用默认配置: +可以在 `resources.json` 中使用默认配置: ```json { @@ -20,7 +18,7 @@ } ``` -玩家在 `bd2client.exe` 中选择“官方 CDN”。资源会由玩家直连官方节点,FRP 只承载认证和游戏 API,不承担数 GB 的 ServerData 流量。 +玩家在 `bd2client.exe` 中选择“官方 CDN”。这样我们的服务器只会承担平常游玩的游戏 API。 ## 获取官方资源镜像 @@ -38,16 +36,9 @@ macOS/Linux(Bash 或 Zsh): ./bd2server resources fetch --output '/srv/bd2-resources' ``` -命令会按照同目录 `versions.json` 中的版本: +命令会按照同目录 `versions.json` 中的版本下载所需的数据。 -- 下载并验证 GameData、`design.version`、ZIP 结构与 CRC。 -- 下载 ServerData catalog,并只同步 catalog 实际引用的 bundle。 -- 拒绝不安全的 catalog 路径。 -- 跳过已经具有有效 `UnityFS` 签名的 bundle。 -- 使用同目录临时文件完成替换。 -- 生成 `resource-fetch-manifest.json`。 - -ServerData 可能达到数 GB。命令不会在普通 `serve` 启动时自动下载整套 ServerData,避免意外消耗大量磁盘和流量。 +ServerData 会达到数 GB。注意合理分配,服务器启动时不会下载这些,只会下载所需的游戏数据文件。 同步结果的目录结构是: @@ -60,7 +51,7 @@ ServerData 可能达到数 GB。命令不会在普通 `serve` 启动时自动下 ## 服务器资源源 -服主自建资源镜像与反代官方 CDN 对客户端来说没有区别:它们都提供两个可公开访问的 HTTP(S) 基础 URL。服务端统一使用 `server` 模式,不会向玩家暴露后端究竟是静态文件、对象存储、边缘 CDN 还是缓存反代。 +服主自建资源镜像与反代官方 CDN 对客户端来说没有区别:它们都提供两个可公开访问的 HTTP(S) 基础 URL。服务端统一使用 `server` 模式。 把上述 `ServerData` 和 `GameData` 目录上传到对象存储、静态 Web 服务器或 CDN 时,资源 URL 必须保留目录层级,并允许普通 `GET` 请求。 @@ -83,11 +74,11 @@ Content-Type: application/json {"cdn_mode":"server"} ``` -服务端会返回经过校验的 URL、Bundle 版本和 GameData 版本。客户端拒绝模式或版本不一致的响应。 +服务端会返回经过校验的 URL、Bundle 版本和 GameData 版本。客户端会拒绝模式或版本不一致的响应。 ### 反代官方 CDN -如果服主不保存完整镜像,也可以把相同的 `server` 配置指向已有边缘 CDN 或带磁盘缓存的 Nginx。反代仍会消耗服主的回源/出口流量,不建议直接放在窄带 FRP 后面。 +如果服主不保存完整镜像,也可以把相同的 `server` 配置指向已有边缘 CDN 或带磁盘缓存的 Nginx。 Nginx 参考配置: diff --git a/SCHEDULES.md b/SCHEDULES.md new file mode 100644 index 0000000..10e871e --- /dev/null +++ b/SCHEDULES.md @@ -0,0 +1,27 @@ +# 项目排期文件 + +服务端从发布目录中的固定 `schedules/` 目录读取全部 `.bd2schedule` 文件,完整校验后合并下发排期。文件采用自定义二进制格式。可在游戏版本不变时单独发布排期文件,覆盖相应文件后重启服务端加载。文件中的游戏和 GameData 版本标签表示协议,排期 `revision` 独立表示日历修订。 + +可使用 +```pwsh +.\build-release.ps1 -SchedulesOnly +``` +单独构建排期文件。 + +## 二进制格式版本 1 + +整数使用小端编码。文件头固定 46 字节: + +| 偏移 | 长度 | 内容 | +| --- | --- | --- | +| 0 | 8 | 魔数 `BD2SCH` 后接两个零字节 | +| 8 | 2 | uint16 格式版本,当前为 1 | +| 10 | 4 | uint32 payload 字节数 | +| 14 | 32 | payload 的 SHA-256 原始摘要 | +| 46 | payload 长度 | 按固定顺序编码的记录 | + +定义在 `go/internal/server/calendar/records.go` ,自行查看。 + +## 更新和验证 + +排期更新由项目维护,相关文件的 revision 随数据修订更新。 \ No newline at end of file diff --git a/build-release.ps1 b/build-release.ps1 index df593a3..d6658af 100644 --- a/build-release.ps1 +++ b/build-release.ps1 @@ -143,7 +143,6 @@ Copy-Item -LiteralPath $versionConfig -Destination (Join-Path $serverPackage 've Copy-Item -LiteralPath $versionConfig -Destination (Join-Path $clientPackage 'versions.json') -Force Copy-Item -LiteralPath (Join-Path $root 'RELEASE.md') -Destination (Join-Path $serverPackage 'README.md') -Force Copy-Item -LiteralPath (Join-Path $root 'AUTHENTICATION.md') -Destination (Join-Path $serverPackage 'AUTHENTICATION.md') -Force -Copy-Item -LiteralPath (Join-Path $root 'RESOURCES.md') -Destination (Join-Path $serverPackage 'RESOURCES.md') -Force Copy-Item -LiteralPath (Join-Path $root 'GAME_CONFIGURATION.md') -Destination (Join-Path $serverPackage 'GAME_CONFIGURATION.md') -Force Copy-Item -LiteralPath (Join-Path $root 'docs\CLIENT.md') -Destination (Join-Path $clientPackage 'README.md') -Force Copy-Item -LiteralPath (Join-Path $root 'LICENSE') -Destination (Join-Path $serverPackage 'LICENSE') -Force diff --git a/docs/CLIENT.md b/docs/CLIENT.md deleted file mode 100644 index 56add50..0000000 --- a/docs/CLIENT.md +++ /dev/null @@ -1,75 +0,0 @@ -# BD2 Client Studio - -BD2 Client Studio 是独立的 Windows / macOS 客户端配置工具,不是服务端,也不包含玩家存档、`auth.db`、OAuth secret 或 master key。Linux 可以运行服务端,但不提供游戏客户端工具。 - -Windows 使用 Wails 和系统 WebView2 Runtime 创建桌面窗口,macOS 使用 Cocoa 和系统 WKWebView。窗口由客户端进程管理;关闭窗口会退出整个工具,退出工具也会关闭窗口。Windows 首次使用前应确保已安装 Microsoft Edge WebView2 Runtime:。 - -当前本机发布脚本只生成 Windows 包。macOS 源码保留,后续找到测试者或公开发布时,将使用 GitHub Actions 的 macOS runner 进行原生构建、测试和 `.app` 打包;目前未完成 macOS 实机验证。 - -启动后会打开配置工作台: - -1. 选择 Brown Dust II 安装目录。Windows 选择包含 `BrownDust II.exe` 的目录;macOS 可选择 `BrownDust II.app` 或它的父目录。 -2. 填写要进入的服务器 origin,例如 `https://play.example.com` 或 `http://127.0.0.1:8080`。 -3. 选择 CDN: - - **官方 CDN**:玩家直接从版本锁定的官方节点下载资源,适合朋友通过 FRP 联机。 - - **本机已下载资源**:选择同时包含 `ServerData` 和 `GameData` 的 CDN 根目录;LI 插件会在游戏进程内启动仅监听 loopback 的只读资源服务。 - - **服主资源**:通过服务器 `PUT /client/resources` 取得版本锁定的资源 URL;服主自建和反代对玩家客户端是同一种模式。 -4. 点击“应用客户端补丁”和“安装 / 更新插件”。 - -工作台的“连接设置”提供“代理 → 设置代理”入口。默认直接连接,不自动读取系统或终端环境中的代理。需要代理时,选择“手动 HTTP 代理”,填写例如 `http://127.0.0.1:12451` 的地址,点击“保存连接设置”,再通过工作台启动游戏。不要填写 Markdown 链接或 SOCKS 地址。 - -代理地址必须包含端口,不包含账号密码、路径或查询参数。HTTP 代理可通过 CONNECT 转发 HTTPS 请求,证书仍正常验证;本机 loopback 地址始终直连。配置同时用于客户端资源策略请求和新启动游戏的 HTTP 请求。修改代理后,需要正常退出游戏再重新启动;浏览器 OAuth 登录仍使用浏览器自身的网络设置。 - -客户端配置写入: - -```text -Windows: <游戏目录>/BepInEx/config/bd2.client.json -macOS: /BepInEx/config/bd2.client.json -``` - -macOS 同时兼容把 BepInEx 放在 `BrownDust II.app/Contents/BepInEx` 的布局;若两个位置都存在,优先使用 App Bundle 外的标准 BepInEx 目录。 - -工具只写入: - -```json -{ - "schema_version": 2, - "server_origin": "https://play.example.com", - "cdn_mode": "official", - "proxy_url": "http://127.0.0.1:12451" -} -``` - -`proxy_url` 可选,省略或留空表示直接连接。 - -`bd2client.exe` 启动时严格读取同目录的 `versions.json`。`game_version` 是支持的官方游戏版本;`client_version` 与 `server_version` 是分别演进的软件发布版本,格式为 `游戏版本+client.X.Y.Z` 与 `游戏版本+server.X.Y.Z`。资源仍由 `bundle_version` 和 `game_data_version` 锁定: - -- 从所选客户端的 `BrownDust II_Data/globalgamemanagers` 读取 Unity `bundleVersion`,必须精确等于 `game_version`。不能使用 `BrownDust II.exe` 的 Windows `FileVersion`,该值是 Unity 引擎版本。 -- 本机资源必须包含当前 `bundle_version` 对应的 `catalog_alpha.json` / `.hash`,以及当前 `game_data_version` 对应的 `common-dbdata.info` / `.bin`。 -- 服主资源接口返回的 Bundle 和 GameData 版本必须分别精确匹配,不能互相替代。 -- `versions.json` 缺失、字段错误、出现未知字段或尾随 JSON 时,客户端工具拒绝启动。 - -本机资源模式会额外保存玩家自己选择的目录: - -```json -{ - "schema_version": 2, - "server_origin": "http://127.0.0.1:8080", - "cdn_mode": "local", - "local_resource_directory": "E:\\bd2\\dl" -} -``` - -本机路径不会发送给服务器。插件不会直接依赖各加载链对 `file://` 的兼容性,而是在游戏进程内通过随机 loopback 端口提供 `GET`、`HEAD` 和单段 Range;该端口不会暴露给局域网。 - -补丁只把 Intro 中的地址替换成固定的本地占位地址,并保留 `resources.assets.bak`。真实服务器地址由 `BD2LocalIdentity.dll` 从 `bd2.client.json` 读取,因此不受 Unity 内置 27-byte URL 替换限制。 - -选择服主资源时,服务器必须在同一版本的 `resources.json` 中启用统一的 `server` 模式;客户端会使用严格的 `PUT /client/resources` 读取版本锁定 URL。客户端不会接受模式不匹配、版本不匹配、非 HTTPS(loopback 除外)或带凭据的资源地址。 - -界面语言按系统时区自动选择:中国大陆、香港、澳门和台湾地区使用简体中文,其他地区使用英文。诊断日志始终使用英文;Windows 保存在 `bd2client.exe` 同目录的 `logs/bd2client.log`,macOS 保存在 `~/Library/Logs/BD2 Client Studio/bd2client.log`。单文件最大 `2 MiB`,并只保留一个 `bd2client.log.1` 备份;日志不会写入 UI session、OAuth token 或 secret。 - -工具需要玩家事先安装 BepInEx。服务端不再安装客户端插件,也不需要知道玩家的 Windows 游戏目录。关闭游戏后再执行补丁或插件安装。 - -补丁与插件安装均可重复安全执行。Intro 已经指向当前占位地址时不会再次改写 `resources.assets`;两个已安装 DLL 与发布包内容一致时不会再次复制,并会明确提示已经完成或已经是最新版本。连接配置仍会按当前界面设置进行原子保存。 - -工作台右上角的“启动游戏”会再次验证所选客户端及精确版本,然后通过 Windows 进程启动或 macOS Launch Services 打开游戏。macOS 不会打开 Terminal。 diff --git a/docs/SCHEDULES.md b/docs/SCHEDULES.md deleted file mode 100644 index 3479063..0000000 --- a/docs/SCHEDULES.md +++ /dev/null @@ -1,48 +0,0 @@ -# 项目排期文件 - -服务端从发布目录中的固定 `schedules/` 目录读取全部 `.bd2schedule` 文件,完整校验后合并下发排期。文件采用项目自定义二进制格式;没有 JSON 排期入口或服主自定义配置功能。项目维护者可在游戏版本不变时单独发布排期文件,覆盖相应文件后重启服务端加载。文件中的游戏和 GameData 版本标签表示协议、静态设计兼容性,排期 `revision` 独立表示日历修订。 - -## 二进制格式版本 1 - -整数使用小端编码。文件头固定 46 字节: - -| 偏移 | 长度 | 内容 | -| --- | --- | --- | -| 0 | 8 | 魔数 `BD2SCH` 后接两个零字节 | -| 8 | 2 | uint16 格式版本,当前为 1 | -| 10 | 4 | uint32 payload 字节数 | -| 14 | 32 | payload 的 SHA-256 原始摘要 | -| 46 | payload 长度 | 按固定顺序编码的记录 | - -payload 首先编码 revision、game version、GameData version 三个字符串,再依次编码事件列表、抽卡列表、StepUp 列表、可选常规内容日历、可选魔物追踪日历、商品列表、活动 Hub 列表、小游戏 Hub 列表。 - -字符串编码为 uint32 字节长度及 UTF-8 字节;列表编码为 uint32 记录数量及逐条记录;可选记录先写 0/1 存在标记;布尔值只允许单字节 0 或 1;身份、数量等整数字段编码为 uint64。每类记录采用显式固定字段顺序,权威定义为 `go/internal/server/calendar/records.go`,不使用反射或嵌入 JSON。单文件最多 8 MiB,单字符串最多 64 KiB,记录总量最多 100000;错误魔数、版本、摘要、长度、布尔值及尾随内容都拒绝加载。 - -记录内时间采用 RFC3339 UTC 字符串并保留毫秒,以保留跨年份和永久窗口语义。永久事件起点 `1969-12-31T15:00:00.000Z` 对应协议有符号 int64 的 `-32400000` 毫秒。它不是无符号巨大日期。二进制校验用于发现文件损坏,不代表密码签名。 - -项目维护者在代码中构建具名 `calendar.Manifest` 并调用 `calendar.MarshalBinary` 生成发行文件;读取使用 `calendar.UnmarshalBinary`。项目不提供从公开 JSON 输入生成排期的服主管理命令。发布时保留所有要下发的排期文件;运行时不从版本化 seed 或抓包补齐缺失数据。 - -## 初始数据来源 - -当前 `local-20261005-1` 保留已有时间、编号和协议标记,没有推算后续官方日程: - -| 文件 | 初始记录 | 原始来源 | -| --- | --- | --- | -| `gacha.bd2schedule` | 普通抽卡 11,StepUp 2 | 已迁移删除的 `go/seed/v2_35_10/gacha_schedule.json` | -| `regular.bd2schedule` | 常规内容 9,regular 标记 5 | 已迁移删除的 `go/seed/v2_35_10/schedule.json` | -| `monster_hunt.bd2schedule` | 魔物追踪窗口 1,历史 78 | 原 `go/seed/v2_35_10/readonly.json` 的 `/MonsterHuntScheduleInfo` | -| `cash_shop.bd2schedule` | 商品窗口 37 | 原 readonly seed 的 `/CashShopInfo` 商品行 | -| `event_hubs.bd2schedule` | 活动 Hub 2,小游戏 slot 6 | 原 readonly seed 的 `/EventHubInfo`、`/MiniGameHubInfo` | -| `events.bd2schedule` | 事件排期 54 | `data/capture/2.35.10/20261001-004259/bodies/000004_response_EventScheduleInfoResponse.pb` | - -事件文件将以上同版本响应的既有身份和起止时间维护为项目日历;捕获的 `is_active` 不复制,由服务端根据当前时间重新计算。来源仅用于审计,运行时不读取抓包。UID 为 0 的多条任务以类型和设计组 ID 区分,不制造公开 UID。任务进度和领奖也使用对应组的独立本地身份。 - -Hub 的 UID 是 Hub 身份;slot 内的 UID 按内容类型引用事件、魔物追踪赛季等不同领域。例如 MonsterHunt slot 引用赛季 77/78。旧 Hub 74 的原始时间和子身份作为归档保留,当前捕获事件列表主要对应 Hub 75;不据此虚构已结束 Hub 的子事件窗口。Hub 的 play_end 与 end 独立保留,setting 可以引用多个 UID。 - -事件类型 8 的 ID 引用 `PackTable.Id`,依据当前客户端 `PackInfo.IsProgressUseScheduleEventPack` 和 `IsFinishEventPackSchedule`;它与 Hub 的 `PackEventHubTable.id`、`packId` 分属不同身份。小游戏 Hub 的 progress_type 表示普通、首次开放或复刻状态,不等于静态小游戏的 eventClearType。 - -商品每日、每周、每月重置时间由运行时根据当前时间生成。`SkyWayScheduleInfo` 的 weekday/bonus 规则仍属于静态 seed,`PassInfo` 和 `SeasonRewardInfo` 属于玩家或奖励域。 - -## 更新和验证 - -排期更新由项目维护,相关文件的 revision 随数据修订更新。仅调整时间无需修改游戏版本;引用不同静态设计时必须更新相应版本标签并校验实际 GameData。加载同时校验跨文件重复身份、时间窗口和可玩设计引用,全部通过才下发。事件类型 0、1、4、5、7、8、9、10、11、12、13、17、19 和 20 至 25 校验对应 GameData;类型 3、6、14、15、16、18 当前仅校验协议范围和格式。魔物追踪可玩窗口校验实际 hunt 设计,归档历史仅校验显示记录格式;小游戏 Hub 的 progress_type 校验状态格式。公共日历保留未来、当前和归档记录,玩法入口及进行中标记根据时间和玩家状态限制。