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