feat: 自动换备用装备 + 背包满自动丢垃圾 (v2.1.0)

新增 AutoGear 服务:
- 护甲/工具耐久过低时自动从背包换上同类备用装备(工具按镐/斧/锹/锄/剑类别,
  护甲按头/胸/腿/脚部位匹配),选剩余耐久最高的候选
- 通过 clickSlot 三段点击交换(拿起旧装备->与背包新装备互换->就位),
  走正规网络包,客户端/服务端同步,单人/多人均可用
- 控制器改为换装优先:能换就不打断挖矿,无备用才暂停/下界返程
- 装备保护状态下持续尝试换装,换上后自动恢复任务

新增 AutoTrash 服务:
- 背包满时自动丢弃 trashItems 清单里的垃圾(默认:圆石/深板岩/凝灰岩/
  泥土/花岗岩/闪长岩/安山岩/下界岩/黑石/玄武岩,GUI 可改)
- 方块类垃圾保留 trashReserve 个(默认 64)供 Baritone 搭路垫脚;
  满背且无其他垃圾可丢时只丢一组腾位,尽量保住搭路方块
- clickSlot(THROW) 丢整组,每 tick 限 4 组防数据包风暴

配套修复:
- NetherMiner: 修复血量低时每帧 cancelAll 导致回程寻路反复被取消卡死的 bug;
  markGearBroken 现在真正触发 RETURN_PORTAL 阶段;产物计数改用注册表 id +
  矿物->掉落物映射 + 任务开始基线(老库存不再被误计为战果)
- 两个 Miner 的背包满判定加 20 tick 去抖,给自动丢垃圾留出腾位时间
- GUI 新增两个开关与垃圾清单编辑区,切换任务/开关时保留输入框未应用的编辑
- 装备低耐久检查的手持工具仅限真正的工具,不再误伤钓鱼竿等杂物
这个提交包含在:
lyizai
2026-08-30 13:12:26 +08:00
父节点 49c6297c41
当前提交 a297d2714d
共修改 10 个文件,包含 543 行新增和 64 行删除
@@ -6,11 +6,12 @@ import autodig.client.config.MineTask;
import autodig.client.miner.NetherMiner;
import autodig.client.miner.OverworldMiner;
import autodig.client.service.AutoEat;
import autodig.client.service.AutoGear;
import autodig.client.service.AutoTrash;
import autodig.client.service.DeathRecorder;
import autodig.client.service.KillAura;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
@@ -18,7 +19,8 @@ import net.minecraft.world.Heightmap;
/**
* 挖矿总控制器:把配置、Baritone 桥接、自动进食、杀戮光环、死亡记录、装备耐久
* 保护和各任务专用挖矿器串起来,驱动一个简单的状态机。
* 保护(自动换备用装备)、背包垃圾清理和各任务专用挖矿器串起来,
* 驱动一个简单的状态机。
*/
public final class DigController {
@@ -30,6 +32,8 @@ public final class DigController {
private final BaritoneBridge bridge = new BaritoneBridge();
private final AutoEat autoEat = new AutoEat();
private final KillAura killAura = new KillAura();
private final AutoGear autoGear = new AutoGear();
private final AutoTrash autoTrash = new AutoTrash();
private final DeathRecorder deathRecorder = new DeathRecorder();
private final OverworldMiner overworld = new OverworldMiner(this.bridge);
private final NetherMiner nether = new NetherMiner(this.bridge);
@@ -52,9 +56,11 @@ public final class DigController {
}
PlayerEntity player = client.player;
// 常驻能力:杀戮光环、自动进食
// 常驻能力:杀戮光环、自动进食、背包满丢垃圾、换装冷却
this.killAura.tick(config);
this.autoEat.tick(config);
this.autoTrash.tick(config);
this.autoGear.tick();
// 死亡处理:死亡瞬间暂停任务,重生后按需回到死亡坐标
this.deathRecorder.tick(config, this::onRespawn);
@@ -64,30 +70,37 @@ public final class DigController {
}
// 装备耐久保护(仅在挖矿任务进行中检查)
if (config.task != MineTask.NONE && this.state != State.GEAR_PROTECTION) {
if (this.isGearLowDurability(config, player)) {
this.preGearState = this.state;
this.bridge.cancelAll();
// 下界模式:装备耐久低时直接返程回主世界
if (config.task == MineTask.NETHER && config.netherAutoReturn) {
this.nether.markGearBroken();
this.setState(State.NETHER, "装备耐久过低,下界返程中");
} else {
this.setState(State.GEAR_PROTECTION, "装备耐久过低,暂停挖矿保装备");
if (config.task != MineTask.NONE) {
boolean gearLow = this.isGearLowDurability(config, player);
if (this.state == State.GEAR_PROTECTION) {
// 保护中持续尝试自动换上备用装备,换上后自动恢复任务
if (config.autoGearSwap && gearLow) {
this.autoGear.handleLowGear(config, player);
gearLow = this.isGearLowDurability(config, player);
}
return;
}
}
// 装备耐久保护恢复
if (this.state == State.GEAR_PROTECTION) {
if (!this.isGearLowDurability(config, player)) {
this.setState(this.preGearState != null ? this.preGearState : State.IDLE,
"装备耐久已恢复,继续挖矿");
this.preGearState = null;
} else {
// 仍在装备保护中,等待玩家换装备
return;
if (!gearLow) {
this.setState(this.preGearState != null ? this.preGearState : State.IDLE,
"装备耐久已恢复,继续挖矿");
this.preGearState = null;
} else {
// 仍在装备保护中,等待换装生效或玩家手动处理
return;
}
} else if (gearLow) {
// 先尝试自动换上背包里的备用装备,能换就不打断挖矿
if (!(config.autoGearSwap && this.autoGear.handleLowGear(config, player))) {
this.preGearState = this.state;
this.bridge.cancelAll();
// 下界模式:无备用装备时直接返程回主世界
if (config.task == MineTask.NETHER && config.netherAutoReturn) {
this.nether.markGearBroken();
this.setState(State.NETHER, "装备耐久过低且无备用装备,下界返程中");
} else {
this.setState(State.GEAR_PROTECTION, "装备耐久过低且无备用装备,暂停挖矿保装备");
}
return;
}
// 换装成功:继续正常流程
}
}
@@ -318,7 +331,7 @@ public final class DigController {
/**
* 检查装备耐久是否过低。
* 护甲:任意一件护甲耐久百分比低于阈值
* 工具:手持工具耐久百分比低于阈值
* 工具:手持工具(镐/斧/锹/锄/剑)耐久百分比低于阈值
*/
private boolean isGearLowDurability(DigConfig config, PlayerEntity player) {
// 护甲耐久检查
@@ -335,10 +348,10 @@ public final class DigController {
}
}
}
// 手持工具耐久检查
// 手持工具耐久检查(只关心真正的工具,不误伤钓鱼竿/打火石等杂物)
if (config.toolDurabilityProtection) {
ItemStack mainHand = player.getMainHandStack();
if (!mainHand.isEmpty() && mainHand.isDamageable()) {
if (AutoGear.isTool(mainHand) && mainHand.isDamageable()) {
int maxDmg = mainHand.getMaxDamage();
int remaining = maxDmg - mainHand.getDamage();
double percent = (double) remaining / maxDmg * 100.0;