fix: 主世界岩浆卡死 + 下界挖矿多项修复 (v2.2.3)

主世界:目标点岩浆卡死——同目标不再重复下发、无进展20秒放弃跳过、绕道仅空闲时低频重发,避免玩家被拉回岩浆边

下界:垃圾清单补灵魂沙/灵魂土/岩浆块/沙砾/下界砖;进食不再被切工具打断;挖矿中不再每秒重发mineByName(解决灵魂沙抽搐/来回折返);寻路失败不再误判完成、自动转移新矿区续挖
这个提交包含在:
lyizai
2026-09-01 13:41:42 +08:00
父节点 248505deee
当前提交 e84ac7cf41
共修改 7 个文件,包含 158 行新增和 30 行删除
@@ -6,11 +6,13 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
@@ -41,6 +43,12 @@ public final class NetherMiner {
/** 背包满去抖阈值(tick):连续这么久都满才认定为真满 */
private static final int FULL_DEBOUNCE_TICKS = 20;
/** Baritone 空闲(附近矿已挖完/寻路失败)连续这么久后,转移到新区域继续找(tick) */
private static final int RELOCATE_TICKS = 60;
/** 转移的随机水平距离(方块) */
private static final int RELOCATE_DISTANCE = 16;
/** 转移寻路超时(毫秒):超过则放弃转移,原地继续挖 */
private static final long RELOCATE_TIMEOUT_MS = 15_000;
/** 常见矿物方块 id -> 掉落物品 id(挖掘产物与方块本身不同的情况) */
private static final Map<String, String> ORE_TO_DROP = Map.ofEntries(
@@ -85,6 +93,14 @@ public final class NetherMiner {
private boolean baselineSet;
/** 背包满连续持续的 tick 数(去抖) */
private int fullTicks;
/** Baritone 空闲连续持续的 tick 数(用于触发转移新区域) */
private int idleTicks;
/** 是否正在转移到新矿区 */
private boolean relocating;
/** 转移目标点 */
private BlockPos relocateTarget;
/** 转移开始时间戳 */
private long relocateStart;
public NetherMiner(BaritoneBridge bridge) {
this.bridge = bridge;
@@ -103,6 +119,10 @@ public final class NetherMiner {
this.baselineCount = 0;
this.baselineSet = false;
this.fullTicks = 0;
this.idleTicks = 0;
this.relocating = false;
this.relocateTarget = null;
this.relocateStart = 0;
}
/**
@@ -189,30 +209,15 @@ public final class NetherMiner {
} else if (this.minedEnough(config, player)) {
// 已挖够目标数量
this.miningStarted = false;
this.relocating = false;
if (config.netherAutoReturn) {
this.stage = Stage.RETURN_PORTAL;
} else {
this.done = true;
}
} else if (this.miningStarted && !this.bridge.isActive()) {
// 挖矿进程已跑完(挖够数量或附近无矿可挖)
this.miningStarted = false;
if (config.netherAutoReturn) {
this.stage = Stage.RETURN_PORTAL;
} else {
this.stage = Stage.GO_COMMIT; // 停在下界继续挖(不返回)
}
} else {
// 先派发挖矿指令;派发成功后 miningStarted 置位,
// 之后才能用 isActive()==false 判定「挖完了」
this.issue(() -> {
List<String> ores = config.getNetherOreList();
if (!ores.isEmpty()) {
int count = config.netherTargetCount > 0 ? config.netherTargetCount : -1;
this.bridge.mineByName(count, ores.toArray(String[]::new));
this.miningStarted = true;
}
});
// 未挖够目标数量:持续挖矿,绝不因 Baritone 空闲误判"任务完成"
this.mineTick(config, player);
}
}
case RETURN_PORTAL -> {
@@ -228,13 +233,76 @@ public final class NetherMiner {
/** 判断是否已挖够目标矿物数量(按背包产物计数,扣除任务开始时的基线)。 */
private boolean minedEnough(DigConfig config, PlayerEntity player) {
this.minedCount = this.countProducts(config, player) - this.baselineCount;
if (config.netherTargetCount <= 0) {
return false; // -1 或 0 表示无限挖
}
this.minedCount = this.countProducts(config, player) - this.baselineCount;
return this.minedCount >= config.netherTargetCount;
}
/**
* 未挖够目标时的挖矿驱动:空闲转移到新矿区、持续派发挖矿指令。
*
* <p>关键:Baritone 空闲(附近矿挖完或寻路失败)时,不再把它当成"任务完成"
* 回主世界,而是转移到附近新位置继续找矿;无限目标(-1)下只要没背包满/
* 血量低/装备耐久低,就一直在下界挖。</p>
*/
private void mineTick(DigConfig config, PlayerEntity player) {
if (this.relocating) {
double d = this.distanceSq(player, this.relocateTarget);
if (d <= 4.0) {
// 已到新矿区
this.relocating = false;
this.relocateTarget = null;
this.miningStarted = false;
} else if (System.currentTimeMillis() - this.relocateStart > RELOCATE_TIMEOUT_MS) {
// 转移超时(目标点不可达):放弃转移,原地继续挖
this.relocating = false;
this.relocateTarget = null;
this.bridge.cancelAll();
} else if (!this.bridge.isActive()) {
// 转移途中寻路失败/停下:重发
this.bridge.gotoBlock(this.relocateTarget);
}
return;
}
if (this.miningStarted && !this.bridge.isActive()) {
// 附近矿已挖完或寻路失败:连续空闲一段时间后转移到新区域继续找
this.idleTicks++;
if (this.idleTicks >= RELOCATE_TICKS) {
this.idleTicks = 0;
this.miningStarted = false;
this.relocateToNewArea(player);
}
return;
}
if (!this.miningStarted) {
this.idleTicks = 0;
List<String> ores = config.getNetherOreList();
if (!ores.isEmpty()) {
// 无限目标(-1),实际战果由 minedEnough 计数
this.bridge.mineByName(-1, ores.toArray(String[]::new));
this.miningStarted = true;
}
}
}
/** 转移到玩家附近的新位置(随机水平偏移),继续找矿。 */
private void relocateToNewArea(PlayerEntity player) {
int dx = ThreadLocalRandom.current().nextInt(-RELOCATE_DISTANCE, RELOCATE_DISTANCE);
int dz = ThreadLocalRandom.current().nextInt(-RELOCATE_DISTANCE, RELOCATE_DISTANCE);
this.relocateTarget = player.getBlockPos().add(dx, 0, dz);
this.relocateStart = System.currentTimeMillis();
this.relocating = true;
this.bridge.gotoBlock(this.relocateTarget);
}
private double distanceSq(PlayerEntity player, BlockPos target) {
double dx = player.getX() - (target.getX() + 0.5);
double dz = player.getZ() - (target.getZ() + 0.5);
return dx * dx + dz * dz;
}
/** 统计背包中目标矿物产物的总数量(方块 id 映射到掉落物 id)。 */
private int countProducts(DigConfig config, PlayerEntity player) {
List<String> ores = config.getNetherOreList();