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,全部通过。
这个提交包含在:
@@ -257,6 +257,42 @@ test('startTask 带配置覆盖时写入该机器人的专属配置', async () =
|
||||
assert.strictEqual(config.targetCount, 5);
|
||||
// 另一个机器人不受影响
|
||||
assert.strictEqual(pool.getConfigFor('BotA').strategy, 1);
|
||||
assert.strictEqual(pool.settingSnapshot('BotB').hasOverrides, true);
|
||||
});
|
||||
|
||||
test('clearBotConfigOverride 清除专属配置后重新继承全局', () => {
|
||||
const { pool } = setup({ config: { strategy: 1, targetCount: 10 } });
|
||||
pool.setBotSetting('BotB', { config: { strategy: 3, targetCount: 5 } });
|
||||
assert.strictEqual(pool.getConfigFor('BotB').strategy, 3);
|
||||
assert.strictEqual(pool.settingSnapshot('BotB').hasOverrides, true);
|
||||
|
||||
const saved = pool.clearBotConfigOverride('BotB');
|
||||
|
||||
assert.strictEqual(saved.hasOverrides, false);
|
||||
assert.strictEqual(pool.getConfigFor('BotB').strategy, 1, '应重新继承全局');
|
||||
assert.strictEqual(pool.getConfigFor('BotB').targetCount, 10);
|
||||
// 清除后应下发到运行时
|
||||
assert.strictEqual(pool.get('BotB').manager.config.strategy, 1);
|
||||
});
|
||||
|
||||
test('专属配置是完整快照:存下后全局改动不再影响它(这正是需要「清除」按钮的原因)', () => {
|
||||
const { pool } = setup({ config: { allowBreak: false } });
|
||||
pool.setBotSetting('BotA', { config: { allowBreak: true } });
|
||||
|
||||
// 改全局
|
||||
const next = normalizeConfig({ allowBreak: false, targetCount: 42 }, pool.config);
|
||||
pool.applyGlobalConfig(next);
|
||||
|
||||
assert.strictEqual(pool.getConfigFor('BotA').allowBreak, true, '专属配置优先于全局');
|
||||
assert.strictEqual(pool.getConfigFor('BotB').targetCount, 42, '没有覆盖的机器人跟随全局');
|
||||
|
||||
pool.clearBotConfigOverride('BotA');
|
||||
assert.strictEqual(pool.getConfigFor('BotA').allowBreak, false, '清除后跟随全局');
|
||||
});
|
||||
|
||||
test('clearBotConfigOverride 对不存在的机器人抛 404', () => {
|
||||
const { pool } = setup();
|
||||
assert.throws(() => pool.clearBotConfigOverride('不存在'), (err) => err.statusCode === 404);
|
||||
});
|
||||
|
||||
test('applyGlobalConfig 下发到全部机器人并保留各自的覆盖', () => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户