docs: 记录「规划→卡住→清空」死循环的确切机制

读 mineflayer-pathfinder 源码定位到:index.js 末尾有「徒劳检测」——
3.5 秒内到不了下一个路径点就 resetPath('stuck') 清空路径。
机器人被墙挡住时必然触发,于是每 3.5 秒一个循环:
路径已生成 → 卡住 → 清空 → 路径已生成 → …

可靠信号:resetPath 每次都会补一对 diggingAborted/diggingCompleted 监听器,
所以日志里出现 MaxListenersExceededWarning: 11 diggingAborted listeners
就说明「路径正在被反复清空」。

另两个清空触发点(排查时注意):
- blockUpdate:路径附近方块一变就 resetPath('block_updated');
- chunkColumnLoad:相邻新区块加载就 resetPath('chunk_loaded'),
  服务器频繁传送时会反复触发,A* 的 thinkTimeout 因每次新建 AStar 而永不到期。

结论:只要被墙挡住,就会无限循环「规划→卡住→清空」,既不放弃目标也不脱困。
需要先把它挪到开阔地;长期应累计 path_reset('stuck') 次数,
连续 N 次就判定「此处出不去」并上报 / 换目标。

同时更新当前拦路虎的优先级:第一是机器人被 /u return 送进王城建筑后出不来
(四向只有西面可走、东面头顶是火把),第二才是装备耐久,第三是 /u return 摔伤。
这个提交包含在:
lyizai
2026-10-01 00:39:46 +08:00
父节点 3a508f6818
当前提交 468c719e37
+36 -7
查看文件
@@ -160,13 +160,42 @@ ls -1d /opt/autostore-bot/backup-* 2>/dev/null | tail -3
**当前扩地的真正拦路虎(按优先级):**
1. **耐久保护**:`lastReturn.reason = "装备耐久过低(主手 剩余耐久 15% ≤ 15%)"`
→ 一启动扩地就 `/u return` 回城并停机,`inputTicks=0`(压根没尝试移动)。
**需要人工修装备**。
2. **机器人掉到了低处**(y=72,王城平台在 y≈146):从该位置规划不出路径,
`pathfinder` 与 `manual` 两种执行器都是 `timeout`。需要先把它带回高处。
3. **⚠️ `/u return` 会造成摔落伤害**:实测 `health 3.79 → 1.24`,
更早一次直接 `fell from a high place` 摔死。回城前应确认落点高度。
1. **机器人被地形困在王城建筑里**:实测 `exits` 四向只有西面可走,东面头顶是 **torch**(火把)
—— 它被 `/u return` 传送进建筑后就出不来了。而此时 `mineflayer-pathfinder`
的「徒劳检测」会把每一段路径都清掉(见下),于是永远在「规划 → 卡住 → 清空 → 规划」里循环:
`blockedTicks` 230/237、净位移 ~0。
2. **装备耐久**:`lastReturn.reason = "装备耐久过低(主手 剩余耐久 15% ≤ 15%)"`
→ 一启动扩地就 `/u return` 回城并停机,`inputTicks=0`。**需要人工修装备**。
3. **⚠️ `/u return` 会造成摔落伤害**:实测 `health 3.79 → 1.24`、`7.8 → 5.6`,
更早一次直接 `fell from a high place` 摔死。回城前应确认落点高度;
而且它把机器人送进建筑内部(见第 1 条),等于「回城即被困」。
### 🎯 死循环的确切机制(2026-10-01,读 mineflayer-pathfinder 源码定位)
`mineflayer-pathfinder/index.js` 末尾的「徒劳检测」:
```js
// check for futility
if (performance.now() - lastNodeTime > 3500) {
resetPath('stuck') // 3.5 秒内到不了下一个路径点 → 清空路径
}
```
机器人被墙挡住时,3.5 秒必然到不了下一个路径点 → `resetPath('stuck')` → 重新规划 →
又卡住 → 又清空。**每 3.5 秒一个循环**,日志表现为 `寻路事件:路径已生成(代价 63.07)`
每 3 秒重复一次;`resetPath` 每次都会补一对 `diggingAborted`/`diggingCompleted` 监听器,
所以日志里还会出现 `MaxListenersExceededWarning: 11 diggingAborted listeners`
—— **这条警告就是「路径被反复清空」的可靠信号**。
另外两个也会清空路径的触发点(排查时注意):
- `blockUpdate`:路径附近的方块一变就 `resetPath('block_updated')`;
- `chunkColumnLoad`:新加载的区块与已访问区块相邻就 `resetPath('chunk_loaded')`
—— 服务器频繁传送机器人时,这个会被反复触发,A* 的 20 秒 `thinkTimeout`
因为每次都新建 AStar 而**永远不会到期**。
**结论:只要机器人被墙挡住,它就会无限循环「规划 → 卡住 → 清空」,
既不会放弃目标也不会自己脱困。** 需要先把它挪到开阔地;长期看应处理
`path_reset('stuck')` 的累计次数(连续 N 次就判定「此处出不去」并上报 / 换目标)。
### ⚠️ 线上实测补充(2026-09-29,**它推翻了下面原有的框架**)