Update all docs: README, AI_KNOWLEDGE_BASE, MOD_DEV_GUIDE, batch_example, SKILL

This commit is contained in:
JianFeeeee
2026-05-30 12:51:05 +08:00
parent 3d70338087
commit 21423a6bb4
4 changed files with 367 additions and 824 deletions

View File

@ -2,348 +2,121 @@
## 概述
本文档规定了一个与外部 AgentAI 助手)对接的《缺氧》(Oxygen Not Included) Mod 应遵循的接口规范、约束条件和最佳实践。遵循此规范开发的 Mod 可与 `oni-agent` 工具链无缝协作
---
本文档规定 ONI Agent Bridge Mod 的接口规范和开发约束
## 1. 通信协议
### 1.1 传输层
- **协议**: HTTP 1.1
- **地址**: `127.0.0.1`(仅本地回环,禁止暴露外部网络)
- **端口**: 由配置文件指定(默认 `23876`
- **编码**: 所有请求和响应均为 UTF-8
- **地址**: `127.0.0.1`(仅本地回环,禁止暴露外部网络)
- **端口**: 默认 `23876`,可在 `config.json` 修改
- **编码**: UTF-8
### 1.2 数据格式
- 所有请求和响应使用 `application/json`
- 响应必须包含有效的 JSON
- 错误响应必须包含 `error` 字段
所有请求和响应使用 `application/json`
**统一响应格式:**
```json
// 成功响应
{ "result": "ok", ... }
// 成功
{ "success": true, "data": { ... } }
// 错误响应
{ "error": "error_message" }
// 错误
{ "success": false, "error": "error_code", "errorMessage": "可读信息" }
```
### 1.3 请求超时
- 服务端应在 5 秒内响应
- 长时间操作应排队后立即返回 `{ "result": "queued" }`
**旧格式兼容**/health 端点历史版本):
```json
{ "status": "ok" }
```
---
### 1.3 线程模型
- **读操作**可通过 `EnqueueRead(Func<object>)` 排队到主线程执行(`ManualResetEvent` 同步等待)
- **写操作**通过静态 `ConcurrentQueue<Action> cmdQueue` + `QueueProcessor` (MonoBehaviour.Update) 排队到主线程
- **格子数据**Grid.Element/Mass/Temperature/Objects可从后台线程直接读取静态数组
## 2. API 端点规范
## 2. 端点规范
### 2.1 健康检查
```
GET /health
```
用于 Agent 探测 Mod 是否存活。必须始终可达,不依赖游戏状态。
**响应**:
必须始终可达,不依赖游戏状态。
```json
{ "status": "ok", "service": "mod_name" }
{ "success": true, "data": { "status": "ok", "service": "oni-agent-bridge", "version": "2.0.0" } }
```
### 2.2 状态查询端点
### 2.2 状态查询 (GET /api/state/)
| 端点 | 说明 | 实现方式 |
|------|------|---------|
| game | 周期/复制人/世界尺寸/暂停/速度 | EnqueueRead |
| resources | 资源列表(含物态/存量) | EnqueueRead |
| buildings | 建筑列表(含位置/尺寸) | EnqueueRead |
| duplicants | 复制人(位置/血量) | EnqueueRead |
| research | 科技进度 | EnqueueRead |
| rooms | 房间类型 | EnqueueRead |
| events | 事件日志(支持since分页) | 直接读取(eventLock) |
| storage | 储物建筑内容 | EnqueueRead |
| saves | 存档列表 | EnqueueRead |
| alert | 游戏警报 | EnqueueRead |
| camera | 相机位置 | EnqueueRead |
所有状态查询为 `GET` 请求,路径前缀 `/api/state/`
| 端点 | 返回内容 | 必需 | 新增字段 |
|------|---------|------|---------|
| `/api/state/game` | 周期、复制人、世界尺寸 | **是** | `gridWidth`, `gridHeight` |
| `/api/state/resources` | 资源列表(含分类/物态) | **是** | `id`, `state`, `category` |
| `/api/state/duplicants` | 复制人详情 | **是** | `x`, `y`, `cell`, `currentChore` |
| `/api/state/buildings` | 建筑列表 | 推荐 | `cell`, `category`, `powerWatt` |
| `/api/state/research` | 科技树(含解锁列表) | 推荐 | `requiredTechs`, `unlockedBuildings` |
| `/api/state/geysers` | 喷泉详情 | 可选 | `cell`, `isActive`, `isDormant` |
| `/api/state/alert` | 当前警报 | 推荐 | `clickable` |
| `/api/state/critters` | 小动物详情 | 可选 | `cell`, `calories` |
| `/api/state/plants` | 植物列表 | 可选 | `isGrown`, `progress`, `isWilting` |
| `/api/state/rooms` | 房间列表 | 可选 | 类型/格数/建筑/生物/植物 |
### 2.3 地图/格子数据端点
这是 AI 理解游戏世界最重要的端点。格子级数据让 AI 知道每个具体位置的状态。
| 端点 | 说明 | 参数 |
### 2.3 格子数据 (GET, 可后台线程)
| 端点 | 参数 | 说明 |
|------|------|------|
| `GET /api/state/cell` | 单格详情 | `?x=&y=` |
| `GET /api/state/cells` | 矩形区域(批量) | `?x=&y=&width=&height=` |
| `GET /api/state/cells/slice` | 行或列扫描 | `?axis=x&index=&start=&end=` |
| `GET /api/state/gas` | 气体分布分析 | `?x=&y=&radius=` |
| cell | x, y | 单格详情 |
| cells | x, y, width, height | 矩形区域 |
| cells/slice | axis, index, start, end | 行列扫描 |
| gas | x, y, radius | 气体分布 |
#### `GET /api/state/cell?x=10&y=5`
### 2.4 注册表 (GET /api/registry/)
| 端点 | 说明 |
|------|------|
| buildings | 所有建筑定义(含尺寸/材料类别) |
| elements | 所有元素定义 |
| techs | 科技树(含前置) |
```json
{
"x": 10, "y": 5, "cell": 4523,
"element": "Oxygen",
"elementId": "Oxygen",
"elementState": "gas",
"massKg": 1.8,
"temperatureC": 23.5,
"isSolid": false, "isLiquid": false, "isGas": true,
"hasBuilding": true, "buildingName": "GasPump",
"hasDuplicant": false, "duplicantName": null,
"isVacuum": false, "isVisible": true
}
### 2.5 操作 (POST /api/action/)
所有操作执行前**自动拉视角**到目标坐标。
| 端点 | 请求体 | 说明 |
|------|--------|------|
| pause | {reason?} | 暂停(通过SpeedControlScreen) |
| unpause | {speed?} | 恢复 |
| speed | {speed} | 设速度 |
| dig | {x,y,width,height} | 挖掘(使用DigTool.PlaceDig) |
| build | {buildingId,x,y} | 建造(使用BuildingDef.Instantiate) |
| deconstruct | {x,y} | 拆除(使用Deconstructable.QueueDeconstruction) |
| prioritize | {x,y,priority} | 设优先级(1-9) |
| research | {techId} | 研究(SetActiveResearch) |
| mop | {x,y} | 清理液体 |
| harvest | {x,y} | 收获植物 |
| batch | {actions} | 批量操作 |
| save | {name?} | 存档 |
| load | {name} | 读档 |
| camera | {x,y,zoom?} | 移动视角 |
| priority_global | {target,priority} | 全局默认优先级 |
| priority_type | {buildingType,priority} | 按类型优先级 |
### 2.6 截图
```
#### `GET /api/state/cells?x=0&y=0&width=5&height=5`
```json
{
"region": { "x": 0, "y": 0, "width": 5, "height": 5 },
"cells": [ /* array of cell objects */ ]
}
GET /api/screenshot/latest
```
返回 PNG 图片。通过 `ScreenCapture.CaptureScreenshot` 异步生成。
### 2.4 实体注册表端点 (AI 参考)
## 3. 事件系统
用于 AI 在运行时查询游戏实体的元数据。所有为 `GET` 请求
Mod 内部维护事件列表 (`List<AgentEvent> + lock`)
事件可通过 `GET /api/state/events?since=N` 轮询。
事件自动记录操作日志。
| 端点 | 返回内容 |
|------|---------|
| `/api/registry/buildings` | 全部建筑定义(尺寸/功耗/发热/材料) |
| `/api/registry/elements` | 全部元素定义(比热容/导热/熔沸点) |
| `/api/registry/techs` | 全部科技定义(前置/解锁建筑) |
## 4. Mod 开发检查清单
#### `GET /api/registry/buildings`
```json
[
{
"id": "Electrolyzer",
"name": "Electrolyzer",
"category": "Oxygen",
"width": 2, "height": 2,
"powerCost": 120,
"heatGeneration": 1.25,
"constructionMass": ["IronOre", "IronOre"]
}
]
```
### 2.5 操作端点
所有操作为 `POST` 请求,路径前缀 `/api/action/`
| 端点 | 作用 | 必需 |
|------|------|------|
| `/api/action/dig` | 挖掘指定区域 | **是** |
| `/api/action/build` | 建造建筑 | **是** |
| `/api/action/deconstruct` | 拆除建筑 | 推荐 |
| `/api/action/prioritize` | 设置优先级 | 可选 |
| `/api/action/research` | 选择研究方向 | 推荐 |
| `/api/action/schedule` | 修改复制人日程 | 可选 |
| `/api/action/wardrobe` | 修改复制人装备 | 可选 |
| `/api/action/mop` | 清理液体 | 推荐 |
| `/api/action/harvest` | 收获植物 | 推荐 |
| `/api/action/cancel` | 取消操作 | 可选 |
#### `GET /api/state/game`
```json
{
"cycle": 42,
"duplicantCount": 6,
"worldName": "Terra",
"worldSize": 256
}
```
#### `GET /api/state/duplicants`
```json
[
{
"name": "Dup1",
"stress": 12.5,
"calories": 850000,
"stamina": 98.2,
"oxygen": 85.0,
"diseases": 0,
"skillLevels": 3
}
]
```
#### `GET /api/state/resources`
```json
[
{ "name": "Oxygen", "tag": "Oxygen", "amount": 12345.6, "unit": "kg" }
]
```
#### `GET /api/state/buildings`
```json
[
{
"name": "Manual Generator",
"id": "ManualGenerator",
"x": 10,
"y": 5,
"isOperational": true
}
]
```
### 2.3 操作端点
所有操作为 `POST` 请求,路径前缀 `/api/action/`
| 端点 | 作用 | 必需 |
|------|------|------|
| `/api/action/dig` | 挖掘指定区域 | **是** |
| `/api/action/build` | 建造建筑 | **是** |
| `/api/action/deconstruct` | 拆除建筑 | 推荐 |
| `/api/action/prioritize` | 设置优先级 | 可选 |
| `/api/action/research` | 选择研究方向 | 推荐 |
| `/api/action/schedule` | 修改复制人日程 | 可选 |
| `/api/action/wardrobe` | 修改复制人装备 | 可选 |
#### `POST /api/action/dig`
**请求体**:
```json
{ "x": 10, "y": 5, "width": 8, "height": 6 }
```
**响应**:
```json
{ "result": "dig_queued", "x": 10, "y": 5, "width": 8, "height": 6 }
```
#### `POST /api/action/build`
**请求体**:
```json
{ "buildingId": "Electrolyzer", "x": 10, "y": 5, "rotation": null }
```
**响应**:
```json
{ "result": "build_queued", "buildingId": "Electrolyzer", "x": 10, "y": 5 }
```
---
## 3. Mod 约束
### 3.1 安全性
1. **仅绑定本地回环地址** `127.0.0.1`,不得监听 `0.0.0.0`
2. **不得实现认证/授权**——回环地址默认安全
3. **不得执行文件 I/O**(读取 Mod 自带配置除外)
4. **输入校验**——所有用户输入必须校验类型和范围
### 3.2 性能
1. 状态查询必须是**只读操作**,不得持有锁
2. 资源列表等大数据量接口应考虑分页(未来扩展)
3. 建造/挖掘等操作应返回 `queued` 后异步执行
4. HTTP 服务器应在**单独线程**运行,不得阻塞游戏主线程
### 3.3 兼容性
1. 使用 `KMod.UserMod2` 基类
2. 使用 `Harmony` 进行补丁(如果使用)
3. 引用 `UnityEngine``Assembly-CSharp` 程序集
4. 最小支持游戏版本应在 `mod_info.yaml` 中声明(当前推荐 `612000`
### 3.4 错误处理
```json
// Mod 内部错误的通用格式
{ "error": "error_type", "details": "human readable message" }
// 常见错误类型
{ "error": "not_found" } // 404 端点不存在
{ "error": "invalid_request" } // 请求体解析失败
{ "error": "not_implemented" } // 功能尚未实现
{ "error": "unknown_building", "buildingId": "..." } // 建筑 ID 不识别
{ "error": "unknown_tech", "techId": "..." } // 科技 ID 不识别
```
---
## 4. 配置文件规范
Agent 侧通过 `config.json` 定位 Mod
```json
{
"modHost": "127.0.0.1",
"modPort": 23876,
"timeout": 10
}
```
- `modHost`: 始终为 `127.0.0.1`
- `modPort`: 应与 Mod 中监听的端口一致
- `timeout`: HTTP 请求超时秒数
---
## 5. AI-Friendly 数据设计原则
### 5.1 数据可读性
所有暴露的数据应满足 AI 可直接理解的三个条件:
1. **命名语义化** — 使用自然语言字段名(如 `temperatureC` 而非 `tempK`)
2. **数据类型合理** — 使用数字而非枚举字符串(温度用 `float` 而非 `string`)
3. **上下文完整** — 每个实体包含足够的位置和状态信息(坐标、类别、是否可运行)
### 5.2 坐标系统
- 统一使用 `(x, y)` 整数坐标,对应游戏网格
- 原点在左下角:`(0, 0)`
- 建筑使用其左下角锚点坐标
- 返回数据中同时提供 `cell` 索引Grid 内部使用)和 `(x, y)` 坐标
### 5.3 实体分类
每个实体(建筑、元素、科技)必须包含分类标签:
- 建筑: `category`Base/Oxygen/Power/Food/...
- 元素: `state`solid/liquid/gas+ `category`metal/water/fuel/...
- 资源: 带 `state``category` 帮助 AI 推理用途
### 5.4 AI 推理辅助
- `/api/registry/*` 端点提供完整的实体元数据查询
- `GET /api/state/gas` 提供区域气体分布统计AI 无法逐格遍历)
- `/api/state/rooms` 提供房间判定结果AI 无法自行判断房间类型)
### 5.5 操作设计
操作设计遵循以下原则:
- **幂等性** — 同个操作重复执行不产生副作用
- **非阻塞** — 操作立即返回 `queued`,异步执行
- **确定性** — 使用绝对坐标 `(x, y)`,不支持"在某个建筑旁边"这类模糊表述
- **输入校验** — 拒绝未知的 `buildingId` 或越界坐标
## 6. 扩展建议
### 5.1 添加新端点
1.`ProcessRequest` 中添加路由匹配
2. 实现对应的处理方法
3. 更新本指南和 `SKILL.md`
### 5.2 蓝图系统
预置的建造方案(蓝图)应满足:
- 坐标相对于原点,便于偏移
- 包含预先挖掘区域
- 建筑顺序隐含依赖关系
### 5.3 事件推送(未来)
考虑支持 WebSocket 或 SSE用于游戏事件实时推送如警报触发
---
## 6. 开发检查清单
- [ ] Mod 继承 `UserMod2`,在 `OnLoad` 中启动 HTTP 服务
- [ ]`OnUnload` 中停止 HTTP 服务
- [ ] 实现全部必需端点health, game, resources, duplicants, dig, build
- [ ] 错误响应包含 `error` 字段
- [ ] 端口号与 `config.json` 一致
- [ ] 仅绑定 `127.0.0.1`
- [ ] 使用 `Newtonsoft.Json`(游戏自带,无需额外依赖)
- [ ] `mod_info.yaml` 声明了正确的游戏版本
- [ ] Mod 类继承 `UserMod2`,重写 `OnLoad(Harmony)`
- [ ]`GameObject + MonoBehaviour` 处理队列,`DontDestroyOnLoad`
- [ ]`HttpListener` 暴露 HTTP 服务,`BeginGetContext` 异步处理
- [ ] 格子数据安全读取:`Grid.Element[]``Grid.Mass[]``Grid.Solid[]``Grid.Objects[,]`
- [ ] 读操作用 `EnqueueRead` 同步到主线程
- [ ] 写操作用 `cmdQueue` 排队到主线程的 `Update()` 中执行
- [ ] 响应统一 `{success, data}``{success, error, errorMessage}`
- [ ] 所有操作自动 `QWithCamera(x,y,action)` 拉视角