海豹 TRPG 骰点核心,开源跑团辅助工具,支持 QQ/Kook/Discord 等。
轻量 · 易用 · 全能
见 使用手册。
- 核心(本仓库):Go 后端代码仓库,也作为海豹的主仓库,Bug 可反馈在该仓库的 issue 中;
- UI:前端代码,基于 Vue3 + ElementPlus 开发;
- 手册:官方手册源码,由 VitePress 驱动;
- 构建:自动构建仓库,用于自动化发布海豹的每日构建包与 Release;
- Android:Android 应用源码;
- ……
注:如无特殊说明,所有代码文件均遵循 MIT 开源协议
编译的 golang 版本为 1.25.0。在 构建 仓库中采用对 go 进行修补的方式以支持 Windows 7 等低版本系统。
因部分依赖库的需求,可能需要配置国内镜像,个人使用 https://goproxy.cn/ 镜像。
本项目要求所有代码使用 goimports 进行格式化。这一行为已经设定在本项目的编辑器配置文件中。
本项目使用 golangci-lint 工具进行静态分析。
此工具对于代码开发不是必要的。但是,本项目的 CI 流程中配置了 linter 检查,不符合规范的代码不能被合入。
因此,强烈推荐开发者在本地安装此工具,请参考这份文档。分析器的相关配置位于 .golangci.toml 文件中。
你可能需要调整编辑器的相关配置,使用 golangci-lint 为默认的分析工具,并开启自动检查。
对于 Visual Studio Code,列出以下配置项供参考:
go.lintTool选择 golangci-lintgo.lintFlags添加一项--fast-onlygo.lintOnSave不能选择 file,因为只分析单个文件会导致无法正确解析符号引用以上配置没有写入项目的统一设置,以允许开发者不本地使用 golangci-lint
下面的命令默认从仓库根目录执行,即包含 go.mod、main.go、ui/ 的目录。
你可以安装 go-task 以执行预置好的任务。安装后可执行:
# 初次编译运行(包括安装依赖和相关工具)
task install run
# 后续编译运行
task run你也可以按照以下步骤手动进行编译运行:
使用 git 拉取项目代码
从已发布的海豹二进制包中,解压 data、lagrange 两个目录到代码目录下。
同时需要在项目的 static/frontend 下放置用于打包进 core 的 ui 静态资源文件,可手动提供,也可通过命令自动从 github 拉取:
go generate ./...放置静态资源大致如下:
static
│
└─frontend
│ CNAME
│ favicon.svg
│ index.html
│
└─assets
打开项目,或使用终端访问项目目录,运行:
go mod download
go install github.com/pointlander/peg@v1.0.1
go build或者直接使用:
go run .启动项目,大功告成!
本仓库同时包含 Go 后端和新版管理前端:
- 后端入口:仓库根目录的
main.go - 前端目录:
ui/ - OpenAPI 描述文件:
ui/openapi.json - 前端生成代码:
ui/src/api/generated/ - 前端开发服务器:默认
http://127.0.0.1:5175 - 后端 UI/API 服务:默认监听
0.0.0.0:3211,本机访问使用http://127.0.0.1:3211
ui/openapi.json 和 ui/src/api/generated/ 是生成产物,已被 .gitignore 忽略,不要手工编辑,也不要提交。
后端需要 Go,当前项目编译版本见上文“golang 开发环境”。前端需要 Node.js 和 pnpm,版本约束写在 ui/package.json:
node --version
pnpm --version
go version第一次准备仓库时执行:
cd /path/to/sealdice-core-newui
go mod download
pnpm --dir ui install如果需要使用 task 统一执行构建任务,还需要安装 go-task。不使用 task 时,下面所有步骤都可以直接用 go、pnpm 手动复现。
只编译 Go 后端,不构建新版前端:
cd /path/to/sealdice-core-newui
go build .该命令会在当前目录生成 sealdice-core(Windows 下为 sealdice-core.exe)。如果只是临时运行,可以跳过二进制产物,直接使用:
cd /path/to/sealdice-core-newui
go run .如果要把新版 V2 UI 一起构建并嵌入到后端静态资源中,使用:
cd /path/to/sealdice-core-newui
task build-with-v2uitask build-with-v2ui 会先执行 test-and-lint 依赖,再执行构建。完整展开后包含:
go test ./...
go vet ./...
goimports -w .
golangci-lint run
mkdir -p temp
go build -o temp/openapi-gen .
./temp/openapi-gen --gen-openapi=./ui/openapi.json
pnpm --dir ui run generate-client
pnpm --dir ui run build:embed:prepared
go build .因此它会先完成 Go 测试和 lint,再刷新 OpenAPI、生成前端 API 客户端、构建可嵌入的 V2 UI,并最终编译后端。注意 goimports -w . 会直接格式化 Go 文件;如果只想避免自动格式化,请使用下面的手动命令链。
后端提供专用参数 --gen-openapi,用于生成 Huma v2 OpenAPI JSON 后退出。
推荐直接使用前端脚本:
cd /path/to/sealdice-core-newui
pnpm --dir ui run generate-openapi该脚本等价于:
cd /path/to/sealdice-core-newui
go run . --gen-openapi=./ui/openapi.json执行成功后,应出现或更新:
ui/openapi.json
如果只想确认该文件是否生成:
cd /path/to/sealdice-core-newui
test -f ui/openapi.json && echo "ui/openapi.json exists"前端使用 @hey-api/openapi-ts 读取 ui/openapi.json,并把 TypeScript 类型、axios client、SDK、Vue Query options 生成到 ui/src/api/generated/。
如果已经有 ui/openapi.json,只生成前端代码:
cd /path/to/sealdice-core-newui
pnpm --dir ui run generate-client如果要从后端重新生成 OpenAPI,再生成前端代码,使用完整命令:
cd /path/to/sealdice-core-newui
pnpm --dir ui run generate-apipnpm --dir ui run generate-api 等价于:
cd /path/to/sealdice-core-newui/ui
pnpm run generate-openapi
pnpm run generate-client执行成功后,应出现或更新:
ui/openapi.json
ui/src/api/generated/
生成代码后建议立刻做一次前端类型检查:
cd /path/to/sealdice-core-newui
pnpm --dir ui run type-check本地开发推荐显式指定后端监听地址,避免不同平台或已有配置影响端口:
cd /path/to/sealdice-core-newui
go run . --address=127.0.0.1:3211也可以先编译再运行:
cd /path/to/sealdice-core-newui
go build .
./sealdice-core --address=127.0.0.1:3211Windows PowerShell 下运行编译产物:
cd C:\path\to\sealdice-core-newui
go build .
.\sealdice-core.exe --address=127.0.0.1:3211后端启动后,浏览器访问:
http://127.0.0.1:3211
默认根路径会直接打开内置的新 UI;如果需要回退到老 UI,可访问:
http://127.0.0.1:3211/old-ui/
如果没有构建并嵌入新 UI,根路径会显示占位页面;这不影响 API 调试。API 路径仍然是同一个后端服务下的:
http://127.0.0.1:3211/sd-api/v2
前端开发态通过 Vite dev server 启动,页面地址默认是:
http://127.0.0.1:5175
前端代码本身使用同源 API 地址。开发时,Vite 会把这些同源请求代理到后端。代理目标由 ui/vite.config.ts 读取,优先级如下:
VITE_API_PROXY_TARGETDEV_PROXY_SERVERVITE_API_BASE_URL- 默认值
http://localhost:3211
推荐在两个终端中分别运行后端和前端。
终端 A,运行后端:
cd /path/to/sealdice-core-newui
go run . --address=127.0.0.1:3211终端 B,运行前端开发服务器:
cd /path/to/sealdice-core-newui
VITE_API_PROXY_TARGET=http://127.0.0.1:3211 pnpm --dir ui run devWindows PowerShell 下设置环境变量并启动前端:
cd C:\path\to\sealdice-core-newui
$env:VITE_API_PROXY_TARGET = "http://127.0.0.1:3211"
pnpm --dir ui run dev启动后访问:
http://127.0.0.1:5175
前端调试时不要直接把页面打开到 http://127.0.0.1:3211/,那是后端内置静态资源路径;开发模式应访问 Vite 的 5175 端口。Vite 会代理以下路径到后端:
/api
/sd-api
/openapi.json
/docs
/schemas
如果后端改了端口,例如:
cd /path/to/sealdice-core-newui
go run . --address=127.0.0.1:4000前端也必须使用相同端口作为代理目标:
cd /path/to/sealdice-core-newui
VITE_API_PROXY_TARGET=http://127.0.0.1:4000 pnpm --dir ui run dev仅做类型检查:
cd /path/to/sealdice-core-newui
pnpm --dir ui run type-check仅做 Vite 生产构建,要求已经存在 ui/src/api/generated/:
cd /path/to/sealdice-core-newui
pnpm --dir ui run build-only完整前端构建,会自动重新生成 OpenAPI 和前端 API 代码:
cd /path/to/sealdice-core-newui
pnpm --dir ui run build如需构建可嵌入 Go 后端的前端产物:
cd /path/to/sealdice-core-newui
pnpm --dir ui run build:embed从 main.go 开始,这里海豹分出了几个线程,一个启动核心并提供服务,另一个提供 ui 的 http 服务。
可以顺藤摸瓜了解海豹如何启动,如何提供服务,如何响应指令。指令响应的部分写在 im_session.go 中
注意有部分代码还在构思中,实际并未使用,例如 CharacterTemplate,请阅读时先 Find Usage 加以区分
dice.go 中的 Dice 结构体存放着各种核心配置,每个 Dice 实例是一个骰子,而每个骰子下面可以挂靠多个端点 (EndPoint)。端点即交互渠道,例如一个 QQ 账号是一个端点。
所有的端点由 IMSession 来统一管理,同样的,这个类也负责接收和分发指令。
可能你会注意到有 IMSession 和 IMSessionLegacy,只看前一个就行,IMSessionLegacy 对应的是 0.99.13 的上古版本之前的数据结构,仅用于升级配置文件。
GroupInfo 是群组信息
GroupPlayerInfo 是玩家信息
海豹使用叫做 PlatformAdapter 的接口来接入平台,只需将接口全部实现,再创建一个 EndPointInfo 塞入当前用户的 IMSession 对象之中即可。
注:每次在 UI 上添加 QQ 账号,其实就是创建了一个 EndPointInfo 对象,并制定 Adapter 为 PlatformAdapterQQOnebot
目前实现的两个 adapter,一个对应 onebot 协议,主要用于 QQ,另一个对应 http,用于 UI 后台的测试窗口。
观察 PlatformAdapterHttp 如何运作起来是一个很好的切入点,因为他非常简单。
对应 dice/ext_xxx.go 系列文件
推荐从 ext_template.go 入手,以 ext_dnd5e.go 为参考,因为这个模块书写时间较晚,相对较为完善。
dice/roll.peg 是海豹的骰点指令文法文件
dice/rollvm.go 是骰点指令虚拟机
1.5 后,已经替换使用 dicescript (RollVM V2) 作为表达式解释器,现有版本不宜轻动。
关于 dicescript 的信息,请移步 https://github.com/sealdice/dicescript
而出于兼容性的考虑,V1 版本的解释器将继续保留,直到 2.0 版本。