v1.2.2: 目标地表高度改取中位数(避免高树孤峰拉高导致一步之隔误判不可达);CALC_FAILED改为先重试再切目标
这个提交包含在:
@@ -89,12 +89,16 @@ public final class BaritoneBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算目标区块内地表高度(方块 Y 上限):
|
* 计算目标区块内地表高度(方块 Y):遍历该区块 16×16 各列,取
|
||||||
* 遍历该区块 16×16 各列,取“排除树叶的实体地表”的最高值,作为高度约束目标。
|
* “排除树叶的实体地表”高度的<b>中位数</b>,作为高度约束目标。
|
||||||
* 区块尚未加载时各列取到 0,max 仍取已加载列;若整块均未加载则返回 0(不约束高度)。
|
*
|
||||||
|
* <p>用中位数而非最大值:高树/孤峰只是少数列(其树干顶也算 MOTION_BLOCKING_NO_LEAVES),
|
||||||
|
* 取最大值会把整个区块的目标高度拉到无法到达的高柱顶,导致一步之隔的平原区块也
|
||||||
|
* CALC_FAILED(v1.2.2 回归);中位数代表区块“通常地表”,天然可达,而地下矿坑的 y
|
||||||
|
* 仍远低于中位,不会被误判为已到达。</p>
|
||||||
*
|
*
|
||||||
* @param chunk 目标区块
|
* @param chunk 目标区块
|
||||||
* @return 地表最高 Y;0 表示暂无法确定(不施加高度约束)
|
* @return 地表高度中位数;≤0 表示暂无法确定(不施加高度约束)
|
||||||
*/
|
*/
|
||||||
private int surfaceY(ChunkPos chunk) {
|
private int surfaceY(ChunkPos chunk) {
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
@@ -104,16 +108,15 @@ public final class BaritoneBridge {
|
|||||||
World world = client.world;
|
World world = client.world;
|
||||||
int x0 = chunk.x() * 16;
|
int x0 = chunk.x() * 16;
|
||||||
int z0 = chunk.z() * 16;
|
int z0 = chunk.z() * 16;
|
||||||
int maxY = 0;
|
int[] ys = new int[256];
|
||||||
|
int n = 0;
|
||||||
for (int bx = x0; bx < x0 + 16; ++bx) {
|
for (int bx = x0; bx < x0 + 16; ++bx) {
|
||||||
for (int bz = z0; bz < z0 + 16; ++bz) {
|
for (int bz = z0; bz < z0 + 16; ++bz) {
|
||||||
int top = world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, bx, bz);
|
ys[n++] = world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, bx, bz);
|
||||||
if (top > maxY) {
|
|
||||||
maxY = top;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxY;
|
java.util.Arrays.sort(ys);
|
||||||
|
return ys[128];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 强制取消当前寻路任务。 */
|
/** 强制取消当前寻路任务。 */
|
||||||
|
|||||||
@@ -336,11 +336,20 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
|||||||
if (this.skipIfTargetClaimed("\u76ee\u6807\u5df2\u88ab\u5360\u9886")) {
|
if (this.skipIfTargetClaimed("\u76ee\u6807\u5df2\u88ab\u5360\u9886")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Baritone 报告路径计算失败(目标不可达,如被悬崖/高山/水体完全隔断):立即跳过,不再傻等超时
|
// Baritone 报告路径计算失败(目标不可达,如被悬崖/高山/水体完全隔断)。
|
||||||
|
// 不立即跳过:CALC_FAILED 常因瞬时能力限制或起点卡位误报,先重新寻路一次
|
||||||
|
//(相当于“往边上走两步再算一遍”),重试耗尽才跳过当前目标。
|
||||||
if (this.pathCalcFailed) {
|
if (this.pathCalcFailed) {
|
||||||
this.pathCalcFailed = false;
|
this.pathCalcFailed = false;
|
||||||
this.log("\u5bfb\u8def\u5931\u8d25\uff08\u76ee\u6807\u4e0d\u53ef\u8fbe\uff09\uff0c\u8df3\u8fc7 " + this.target.x() + "," + this.target.z());
|
++this.retryCount;
|
||||||
this.setState(State.FAIL, "\u5bfb\u8def\u5931\u8d25");
|
if (this.retryCount >= this.config.retries) {
|
||||||
|
this.log("\u5bfb\u8def\u5931\u8d25\uff08\u76ee\u6807\u4e0d\u53ef\u8fbe\uff09\uff0c\u91cd\u8bd5\u8017\u5c3d\uff0c\u8df3\u8fc7 " + this.target.x() + "," + this.target.z());
|
||||||
|
this.setState(State.FAIL, "\u5bfb\u8def\u5931\u8d25");
|
||||||
|
} else {
|
||||||
|
this.log("\u5bfb\u8def\u5931\u8d25\uff08\u76ee\u6807\u4e0d\u53ef\u8fbe\uff09\uff0c\u91cd\u65b0\u5bfb\u8def " + this.retryCount + "/" + this.config.retries);
|
||||||
|
this.dataService.refreshAsync();
|
||||||
|
this.retrySameTarget("\u5bfb\u8def\u5931\u8d25\uff0c\u91cd\u65b0\u5bfb\u8def");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 目标已不再与己方领土接壤(地图刷新后边界变化):立即跳过,避免走到无效区块
|
// 目标已不再与己方领土接壤(地图刷新后边界变化):立即跳过,避免走到无效区块
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户