fix: 定位「寻路恒定 47 节点」的根因(专属配置被冻结)并改为按进度判超时
找到「寻路怎么调都只探索 47 个节点」的真凶 - 启动任务时若带了配置,会被整份存为该机器人的专属配置覆盖。它是一份**完整快照**, 等于把当时那一刻的全局配置冻结在这个机器人身上,之后改全局配置再也影响不到它。 实测这台机器人的覆盖里 allowBreak/allowParkour 都是 false,所以我前面所有 「放开挖方块 / 跑酷 / 不限搜索半径」的排查全部无效,一直在跟同一份旧配置较劲。 - 清除覆盖后寻路器的邻居生成数从 **2 变成 15**,机器人开始真正移动。 - 现在保存覆盖时会明确记一条日志(含策略/邦国/数量),说明「此后全局改动不影响它」。 - 新增「清除专属配置」按钮与 POST /api/bots/:id/settings/clear-config, 并在配置面板提示该机器人是否有专属覆盖 —— 这是「改了全局却没生效」的唯一退路。 寻路超时改为按进度判定 - 原来只看墙钟时间:目标常在几百格外,而寻路速度受地形与反作弊回弹影响可能只有 正常步行的十分之一,于是「走得慢但在稳步接近」会被误判成卡死,然后 /u return 回城把进度全部清零。现在只要与目标的曼哈顿距离有实质缩短就重置这一段计时。 - 首次观察只记录距离基准、不续期,保证「原地不动」仍会照常超时。 新增寻路诊断(排查这类问题的关键手段) - GET /api/bots/:id/status 的 pathingDiag 暴露:起点可走邻居数与具体坐标、 寻路器能否通过 world.getBlock 读到方块、四向可见距离。 - 邻居数极少(如 2)说明不是目标太远,而是移动生成器从起点就找不到分支, 此时调任何搜索参数都没用。 测试 355 -> 360,全部通过。
这个提交包含在:
@@ -35,6 +35,15 @@ const State = {
|
||||
/** 环形日志中「导出日志」用的状态摘要键名 */
|
||||
const EXPORT_SUMMARY_KEYS = ['状态', '目标区块', '玩家区块', '队列', '已占领', '重试', '最近进度'];
|
||||
|
||||
/**
|
||||
* 判定「寻路有进展」的最小距离变化(区块)。
|
||||
*
|
||||
* 只要与目标的曼哈顿距离缩短了这么多,就认为是在稳步接近而不是卡死,
|
||||
* 从而重置超时计时。取 1 是因为矿区/建筑区里寻路速度可能远低于正常步行,
|
||||
* 阈值再大就会把慢速推进误判成超时。
|
||||
*/
|
||||
const PATH_PROGRESS_MIN_CHUNKS = 1;
|
||||
|
||||
/**
|
||||
* 自动扩地控制器:扩地任务的核心状态机。
|
||||
*
|
||||
@@ -90,6 +99,8 @@ class ExpansionController {
|
||||
this.retryCount = 0;
|
||||
/** 当前阶段(寻路 / 等待)的开始时间戳 */
|
||||
this.stageStartedMillis = 0;
|
||||
/** 上一次记录的「与目标的曼哈顿距离」,用于判断寻路是否在稳步推进 */
|
||||
this._lastTargetDistance = null;
|
||||
/** 最近一次开垦进度(0-100) */
|
||||
this.lastProgress = 0;
|
||||
|
||||
@@ -344,6 +355,8 @@ class ExpansionController {
|
||||
*/
|
||||
async plan() {
|
||||
const bm = this.botManager;
|
||||
// 重新规划意味着目标可能变了(或被回城传送重置了位置),进度基准必须清空
|
||||
this._lastTargetDistance = null;
|
||||
if (this.config.targetCount > 0 && this.completedClaims >= this.config.targetCount) {
|
||||
this.finish();
|
||||
return;
|
||||
@@ -436,6 +449,20 @@ class ExpansionController {
|
||||
return;
|
||||
}
|
||||
const elapsedSeconds = Math.floor((Date.now() - this.stageStartedMillis) / 1000);
|
||||
// 「有没有在推进」比「花了多久」更能说明问题:
|
||||
// 目标常常在几百格外,而寻路速度受地形与反作弊回弹影响可能只有正常步行的十分之一,
|
||||
// 只看墙钟时间会把「走得慢但在稳步接近」误判成卡死,然后回城传送把进度全部清零。
|
||||
// 因此只要与目标的曼哈顿距离有实质缩短,就重置这一段计时。
|
||||
const distance = chunkPos.manhattan(this.playerChunk, this.target);
|
||||
if (this._lastTargetDistance === null) {
|
||||
// 首次观察只记基准,不动计时 —— 否则每个目标的第一 tick 都会被无条件续期
|
||||
this._lastTargetDistance = distance;
|
||||
} else if (distance <= this._lastTargetDistance - PATH_PROGRESS_MIN_CHUNKS) {
|
||||
this._lastTargetDistance = distance;
|
||||
this.stageStartedMillis = Date.now();
|
||||
this.consecutiveTimeoutMillis = 0;
|
||||
return;
|
||||
}
|
||||
if (elapsedSeconds >= this.config.waitTimeoutSeconds) {
|
||||
this.retryCount++;
|
||||
this.dataService.refreshAsync();
|
||||
|
||||
在新工单中引用
屏蔽一个用户