v1.2.5: 高度偏好寻路(优先往高处走) + 寻路/重试前校验目标接壤 + 超时先走两步再传送
- 新增 GoalXZAltitude 寻路目标:启发式成本 = 水平距离 - 高度权重×y,y 越大优先级越高、y 越小施惩罚,引导寻路优先走高 - ExpansionConfig 新增 altitudePreference/altitudeWeight 配置(默认开/0.1),BaritoneBridge 按配置选择原生 GoalXZ 或高度偏好 Goal - 寻路/重试前先检查目标区块是否仍与己方领土接壤(startPathing/retrySameTarget),不接壤立即跳过 - 寻路超时不再直接传送:重试耗尽后先往边上走两步自救(每轮重试原目标,最多 sideStepMaxRounds=3 轮),多轮无效才按连续超时阈值回城或切换目标
这个提交包含在:
@@ -100,8 +100,8 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
private long consecutiveTimeoutMillis;
|
||||
/** 发送 /u return 回城指令的时间戳(RETURNING 状态使用,用于等待传送完成) */
|
||||
private long returnStartMillis;
|
||||
/** 当前目标是否已使用过"往边上走两步"策略(重试耗尽时先用它,避免重复;再次耗尽才切换目标) */
|
||||
private boolean sideStepAttempted;
|
||||
/** 当前目标已触发"往边上走两步"的次数(每次重试耗尽先走两步再试,达上限才切换目标/回城) */
|
||||
private int sideStepCount;
|
||||
/** 是否正在"往边上走两步"阶段(手动向目标连线垂直方向走开约 2.5 格再重试) */
|
||||
private boolean sideStepping;
|
||||
/** 边走两步的方向符号(+1 左侧 / -1 右侧),被挡时换另一侧 */
|
||||
@@ -229,7 +229,7 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
this.completedClaims = 0;
|
||||
this.retryCount = 0;
|
||||
this.consecutiveTimeoutMillis = 0L;
|
||||
this.sideStepAttempted = false;
|
||||
this.sideStepCount = 0;
|
||||
this.sideStepping = false;
|
||||
this.queue.clear();
|
||||
this.claimedSet.clear();
|
||||
@@ -369,8 +369,12 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
|
||||
/** 让 Baritone 寻路前往当前目标区块,并进入 PATHING 状态 */
|
||||
private void startPathing() {
|
||||
// 寻路前先校验目标区块是否仍与己方领土接壤(地图异步刷新后可能已不接壤),不接壤则直接跳过
|
||||
if (this.skipIfTargetNotAdjacent()) {
|
||||
return;
|
||||
}
|
||||
this.retryCount = 0;
|
||||
this.sideStepAttempted = false;
|
||||
this.sideStepCount = 0;
|
||||
this.stageStartedMillis = System.currentTimeMillis();
|
||||
this.lastProgress = 0;
|
||||
this.baritoneBridge.pathTo(this.target);
|
||||
@@ -398,8 +402,8 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
this.pathCalcFailed = false;
|
||||
++this.retryCount;
|
||||
if (this.retryCount >= this.config.retries) {
|
||||
// 重试耗尽:不直接切换目标,先"往边上走两步"再重试一次;仍失败才交给回城/切换处理
|
||||
if (!this.sideStepAttempted) {
|
||||
// 重试耗尽:不直接切换目标/回城,先"往边上走两步"再重试原目标;可反复多轮,达上限才交给回城/切换
|
||||
if (this.sideStepCount < this.config.sideStepMaxRounds) {
|
||||
this.startSideStep();
|
||||
} else {
|
||||
this.giveUpTarget("\u5bfb\u8def\u5931\u8d25\uff08\u76ee\u6807\u4e0d\u53ef\u8fbe\uff09");
|
||||
@@ -436,11 +440,11 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
// 未耗尽:重新寻路(而非回城),取消旧路径并重新计算,往往"在边上走走"就能走出困境
|
||||
this.log("\u5bfb\u8def\u8d85\u65f6\uff0c\u91cd\u65b0\u5bfb\u8def " + this.retryCount + "/" + this.config.retries);
|
||||
this.retrySameTarget("\u5bfb\u8def\u8d85\u65f6\uff0c\u91cd\u65b0\u5bfb\u8def");
|
||||
} else if (!this.sideStepAttempted) {
|
||||
// 重试耗尽:先不切换目标,用"往边上走两步"再重试一次(走开障碍后重新寻路原目标)
|
||||
} else if (this.sideStepCount < this.config.sideStepMaxRounds) {
|
||||
// 重试耗尽:先不切换目标/回城,用"往边上走两步"再重试一次(走开障碍后重新寻路原目标);可反复多轮
|
||||
this.startSideStep();
|
||||
} else {
|
||||
// 走两步也未能脱困:连续超时达到阈值则回城传送重新开始,否则切换目标
|
||||
// 多轮走两步也未能脱困:连续超时达到阈值则回城传送重新开始,否则切换目标
|
||||
this.giveUpTarget("\u5bfb\u8def\u8d85\u65f6");
|
||||
}
|
||||
}
|
||||
@@ -486,19 +490,19 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
/**
|
||||
* 目标寻路重试耗尽时的脱困策略入口:
|
||||
* 取消当前寻路,改为手动朝"目标连线垂直方向"走开约 2.5 格(左右各试一侧),
|
||||
* 走开后自动重新寻路原目标;走不开/超时则交给 {@link #giveUpTarget} 回城或切换目标。
|
||||
* 每个目标最多触发一次(sideStepAttempted 标志在 startPathing 时重置)。
|
||||
* 走开后自动重新寻路原目标;走不开/超时则再走两步或交给 {@link #giveUpTarget} 回城/切换目标。
|
||||
* 每个目标最多触发 {@code sideStepMaxRounds} 轮(sideStepCount 在 startPathing 时重置)。
|
||||
*/
|
||||
private void startSideStep() {
|
||||
this.baritoneBridge.cancel();
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
this.sideStepping = true;
|
||||
this.sideStepAttempted = true;
|
||||
++this.sideStepCount;
|
||||
this.sideStepSign = 1; // 默认先朝目标连线左侧走
|
||||
this.sideStepStartPos = client != null && client.player != null ? client.player.getBlockPos() : null;
|
||||
this.sideStepDeadlineMillis = System.currentTimeMillis() + 10000L; // 整体最多走 10 秒
|
||||
this.sideStepSinceMillis = System.currentTimeMillis();
|
||||
this.log("\u5bfb\u8def\u91cd\u8bd5\u8017\u5c3d\uff0c\u5f00\u59cb\u5f80\u8fb9\u4e0a\u8d70\u4e24\u6b65\u518d\u91cd\u8bd5\u539f\u76ee\u6807");
|
||||
this.log("\u5bfb\u8def\u91cd\u8bd5\u8017\u5c3d\uff0c\u5f00\u59cb\u5f80\u8fb9\u4e0a\u8d70\u4e24\u6b65\u518d\u91cd\u8bd5\u539f\u76ee\u6807\uff08\u7b2c " + this.sideStepCount + "/" + this.config.sideStepMaxRounds + " \u8f6e\uff09");
|
||||
this.setState(State.PATHING, "\u5f80\u8fb9\u4e0a\u8d70\u4e24\u6b65...");
|
||||
}
|
||||
|
||||
@@ -606,10 +610,13 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
||||
|
||||
/** 重试当前目标:取消旧寻路,重新让 Baritone 前往同一目标区块 */
|
||||
private void retrySameTarget(String statusText) {
|
||||
// 目标已被他人占领(地图刷新后发现):不再重试,直接跳过,避免玩家被困在已占领区块
|
||||
// 重试前先校验目标有效性:已被他人占领或已不接壤时不再重试,直接跳过,避免玩家被困在无效区块
|
||||
if (this.skipIfTargetClaimed("\u91cd\u8bd5\u65f6\u53d1\u73b0\u76ee\u6807\u5df2\u88ab\u5360\u9886")) {
|
||||
return;
|
||||
}
|
||||
if (this.skipIfTargetNotAdjacent()) {
|
||||
return;
|
||||
}
|
||||
this.baritoneBridge.cancel();
|
||||
this.stageStartedMillis = System.currentTimeMillis();
|
||||
this.baritoneBridge.pathTo(this.target);
|
||||
|
||||
在新工单中引用
屏蔽一个用户