# ONI Agent Mod 开发指南 ## 概述 本文档规定了一个与外部 Agent(AI 助手)对接的《缺氧》(Oxygen Not Included) Mod 应遵循的接口规范、约束条件和最佳实践。遵循此规范开发的 Mod 可与 `oni-agent` 工具链无缝协作。 --- ## 1. 通信协议 ### 1.1 传输层 - **协议**: HTTP 1.1 - **地址**: `127.0.0.1`(仅本地回环,禁止暴露到外部网络) - **端口**: 由配置文件指定(默认 `23876`) - **编码**: 所有请求和响应均为 UTF-8 ### 1.2 数据格式 - 所有请求和响应使用 `application/json` - 响应必须包含有效的 JSON - 错误响应必须包含 `error` 字段 ```json // 成功响应 { "result": "ok", ... } // 错误响应 { "error": "error_message" } ``` ### 1.3 请求超时 - 服务端应在 5 秒内响应 - 长时间操作应排队后立即返回 `{ "result": "queued" }` --- ## 2. API 端点规范 ### 2.1 健康检查 ``` GET /health ``` 用于 Agent 探测 Mod 是否存活。必须始终可达,不依赖游戏状态。 **响应**: ```json { "status": "ok", "service": "mod_name" } ``` ### 2.2 状态查询端点 所有状态查询为 `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 知道每个具体位置的状态。 | 端点 | 说明 | 参数 | |------|------|------| | `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=` | #### `GET /api/state/cell?x=10&y=5` ```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 } ``` #### `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 */ ] } ``` ### 2.4 实体注册表端点 (AI 参考) 用于 AI 在运行时查询游戏实体的元数据。所有为 `GET` 请求。 | 端点 | 返回内容 | |------|---------| | `/api/registry/buildings` | 全部建筑定义(尺寸/功耗/发热/材料) | | `/api/registry/elements` | 全部元素定义(比热容/导热/熔沸点) | | `/api/registry/techs` | 全部科技定义(前置/解锁建筑) | #### `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` - [ ] 使用 `System.Text.Json` 而不是 `Newtonsoft.Json`(减少依赖) - [ ] `mod_info.yaml` 声明了正确的游戏版本