feat: v2.2.2 无路时自动搭方块(可开关)
- Baritone allowPlace/allowParkourPlace 改为配置驱动(默认开) - 新增 AutoScaffold 服务:快捷栏搭路方块不足时自动从背包补给 (只进空位/只与更小的搭路方块堆交换,不碰工具食物) - 搭路方块清单喂给 Baritone acceptableThrowawayItems(放置时从中挑选) - AutoTrash 永不丢弃快捷栏物品,与搭路补给协同 - GUI 新增开关与搭路方块清单设置;版本升至 2.2.2
这个提交包含在:
@@ -10,11 +10,12 @@
|
|||||||
- **目标矿物 id**:带不带 `minecraft:` 前缀均可识别(如 `diamond_ore` 与 `minecraft:diamond_ore` 等价)。
|
- **目标矿物 id**:带不带 `minecraft:` 前缀均可识别(如 `diamond_ore` 与 `minecraft:diamond_ore` 等价)。
|
||||||
|
|
||||||
### 智能辅助(可逐项开关)
|
### 智能辅助(可逐项开关)
|
||||||
|
- **无路自动搭方块**:开启后 Baritone 在没有路时(深渊、缺口、岩浆挡路)自动放置方块搭桥/垫脚;模组会自动把背包里的搭路方块(按清单)补进快捷栏供其使用,快捷栏物品永不自动丢弃。
|
||||||
- **工具自动选择**:挖掘前校验手持工具能否采掘目标矿物(如远古残骸必须钻石镐以上,铁镐只会白挖不掉落),不适用时自动从背包换上能采掘且耐久最高的工具;没有合适工具时提示并暂停矿物挖掘,放入工具后自动恢复。
|
- **工具自动选择**:挖掘前校验手持工具能否采掘目标矿物(如远古残骸必须钻石镐以上,铁镐只会白挖不掉落),不适用时自动从背包换上能采掘且耐久最高的工具;没有合适工具时提示并暂停矿物挖掘,放入工具后自动恢复。
|
||||||
- **自动切换工具**:由 Baritone 在挖掘途中自动选择最合适的工具。
|
- **自动切换工具**:由 Baritone 在挖掘途中自动选择最合适的工具。
|
||||||
- **自动进食**:饥饿度低时自动吃背包食物,跳过金苹果等特殊/珍贵食物。
|
- **自动进食**:饥饿度低时自动吃背包食物,跳过金苹果等特殊/珍贵食物。
|
||||||
- **自动换备用装备**:护甲/工具耐久过低时自动从背包换上同类备用装备。
|
- **自动换备用装备**:护甲/工具耐久过低时自动从背包换上同类备用装备。
|
||||||
- **提前丢垃圾**:背包接近满(已用 ≥30 格)时就提前丢弃圆石、深板岩等垃圾,为矿物腾出空间,避免被误判"背包已满需返回"。
|
- **提前丢垃圾**:背包接近满(已用 ≥30 格)时就提前丢弃圆石、深板岩等垃圾,为矿物腾出空间,避免被误判"背包已满需返回";快捷栏物品(搭路方块/工具/食物)永不丢弃。
|
||||||
- **杀戮光环**:自动攻击附近真正敌对生物,不误伤铁傀儡、僵尸猪灵、末影人等中立生物。
|
- **杀戮光环**:自动攻击附近真正敌对生物,不误伤铁傀儡、僵尸猪灵、末影人等中立生物。
|
||||||
- **保命优先**:血线过低时暂停挖矿向上撤离,恢复后自动续任务。
|
- **保命优先**:血线过低时暂停挖矿向上撤离,恢复后自动续任务。
|
||||||
- **装备耐久保护**:护甲/工具耐久低于阈值时暂停或换装,下界模式直接返程。
|
- **装备耐久保护**:护甲/工具耐久低于阈值时暂停或换装,下界模式直接返程。
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
|
|
||||||
## 版本记录
|
## 版本记录
|
||||||
|
|
||||||
|
- **v2.2.2**:新增无路自动搭方块(可开关):Baritone 放置方块搭桥/垫脚,自动补给快捷栏搭路方块并喂给 Baritone 可放置物品清单;AutoTrash 不再丢弃快捷栏物品。
|
||||||
- **v2.2.1**:移除自动火把;新增主世界矿物绕道挖掘(附近 10 格目标矿物自动挖掉,不漏矿);新增工具适用性检查(远古残骸等自动换钻石镐);支巷长度可配置(默认 10);矿物 id 兼容 `minecraft:` 前缀。
|
- **v2.2.1**:移除自动火把;新增主世界矿物绕道挖掘(附近 10 格目标矿物自动挖掉,不漏矿);新增工具适用性检查(远古残骸等自动换钻石镐);支巷长度可配置(默认 10);矿物 id 兼容 `minecraft:` 前缀。
|
||||||
- **v2.2.0**:新增实时状态 HUD、`/autodig status` 命令;自动进食跳过特殊食物;背包接近满提前丢垃圾防误判返程;杀戮光环不再误伤中立生物;GUI 补全进食/保命/攻击范围等设置。
|
- **v2.2.0**:新增实时状态 HUD、`/autodig status` 命令;自动进食跳过特殊食物;背包接近满提前丢垃圾防误判返程;杀戮光环不再误伤中立生物;GUI 补全进食/保命/攻击范围等设置。
|
||||||
- **v2.1.0**:自动换备用装备 + 背包满自动丢垃圾。
|
- **v2.1.0**:自动换备用装备 + 背包满自动丢垃圾。
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ yarn_mappings=1.21.4+build.8
|
|||||||
loader_version=0.19.3
|
loader_version=0.19.3
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=2.2.1
|
mod_version=2.2.2
|
||||||
maven_group=autodig
|
maven_group=autodig
|
||||||
archives_base_name=autodig
|
archives_base_name=autodig
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,22 @@ import baritone.api.BaritoneAPI;
|
|||||||
import baritone.api.IBaritone;
|
import baritone.api.IBaritone;
|
||||||
import baritone.api.Settings;
|
import baritone.api.Settings;
|
||||||
import baritone.api.utils.BlockOptionalMeta;
|
import baritone.api.utils.BlockOptionalMeta;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Baritone API 封装(桥接层)。
|
* Baritone API 封装(桥接层)。
|
||||||
*
|
*
|
||||||
* <p>把模组对 Baritone 的所有调用集中在此类:同步用户配置(工具切换、避岩浆、
|
* <p>把模组对 Baritone 的所有调用集中在此类:同步用户配置(工具切换、避岩浆、
|
||||||
* 避怪、保命优先)、按名字/数量挖矿、前往指定坐标、前往最近传送门、
|
* 避怪、保命优先、无路时放置方块搭路)、按名字/数量挖矿、前往指定坐标、
|
||||||
* 取消任务等。(杀戮光环由 KillAura 近战实现,不经 Baritone。)</p>
|
* 前往最近传送门、取消任务等。(杀戮光环由 KillAura 近战实现,不经 Baritone。)</p>
|
||||||
*
|
*
|
||||||
* <p>所有调用都做空安全保护,Baritone 未加载时相关操作会安全地静默失败。</p>
|
* <p>所有调用都做空安全保护,Baritone 未加载时相关操作会安全地静默失败。</p>
|
||||||
*/
|
*/
|
||||||
@@ -23,6 +28,9 @@ public final class BaritoneBridge {
|
|||||||
|
|
||||||
/** 上一次打印 gotoBlock 诊断日志的时间戳,用于节流 */
|
/** 上一次打印 gotoBlock 诊断日志的时间戳,用于节流 */
|
||||||
private long lastGotoLog;
|
private long lastGotoLog;
|
||||||
|
/** 搭路方块缓存:原始配置串未变化时直接复用,避免每 tick 解析 */
|
||||||
|
private String lastScaffoldRaw;
|
||||||
|
private List<Item> scaffoldItemsCache = List.of();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把模组配置同步到 Baritone 全局设置。
|
* 把模组配置同步到 Baritone 全局设置。
|
||||||
@@ -34,9 +42,9 @@ public final class BaritoneBridge {
|
|||||||
Settings settings = BaritoneAPI.getSettings();
|
Settings settings = BaritoneAPI.getSettings();
|
||||||
settings.allowSprint.value = true;
|
settings.allowSprint.value = true;
|
||||||
settings.allowBreak.value = true; // 挖矿必须允许挖方块
|
settings.allowBreak.value = true; // 挖矿必须允许挖方块
|
||||||
settings.allowPlace.value = true; // 允许搭路/垫脚
|
settings.allowPlace.value = config.allowPlace; // 无路时放置方块(搭桥/垫脚),可关
|
||||||
|
settings.allowParkourPlace.value = config.allowPlace; // 跑酷垫脚同样受开关控制
|
||||||
settings.allowParkour.value = true;
|
settings.allowParkour.value = true;
|
||||||
settings.allowParkourPlace.value = true;
|
|
||||||
settings.freeLook.value = true;
|
settings.freeLook.value = true;
|
||||||
// 自动切换最合适工具
|
// 自动切换最合适工具
|
||||||
settings.autoTool.value = config.autoTool;
|
settings.autoTool.value = config.autoTool;
|
||||||
@@ -47,11 +55,41 @@ public final class BaritoneBridge {
|
|||||||
settings.blocksToAvoid.value = config.avoidLava
|
settings.blocksToAvoid.value = config.avoidLava
|
||||||
? List.of(Blocks.LAVA)
|
? List.of(Blocks.LAVA)
|
||||||
: List.of();
|
: List.of();
|
||||||
|
// 搭路方块:喂给 Baritone 的可放置/可消耗物品清单(放方块时从中挑选)
|
||||||
|
settings.acceptableThrowawayItems.value = this.scaffoldItems(config);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
// Baritone 未就绪时静默失败,避免抛出异常中断每帧逻辑
|
// Baritone 未就绪时静默失败,避免抛出异常中断每帧逻辑
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析搭路方块清单为物品列表(带缓存,配置串不变时不重复解析)。
|
||||||
|
* 无法识别的 id 跳过;清单为空时返回空列表(Baritone 沿用其默认清单)。
|
||||||
|
*/
|
||||||
|
private List<Item> scaffoldItems(DigConfig config) {
|
||||||
|
String raw = config.scaffoldBlocks;
|
||||||
|
if (raw == null || raw.isBlank()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
if (raw.equals(this.lastScaffoldRaw)) {
|
||||||
|
return this.scaffoldItemsCache;
|
||||||
|
}
|
||||||
|
List<Item> items = new ArrayList<>();
|
||||||
|
for (String name : config.getScaffoldItemList()) {
|
||||||
|
Identifier id = Identifier.tryParse(name.contains(":") ? name : "minecraft:" + name);
|
||||||
|
if (id == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Item item = Registries.ITEM.get(id);
|
||||||
|
if (item != null && item != Items.AIR) {
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lastScaffoldRaw = raw;
|
||||||
|
this.scaffoldItemsCache = items;
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按方块 id 挖指定数量的矿。
|
* 按方块 id 挖指定数量的矿。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ public final class ConfigStore {
|
|||||||
if (c.trashItems == null || c.trashItems.isBlank()) {
|
if (c.trashItems == null || c.trashItems.isBlank()) {
|
||||||
c.trashItems = "cobblestone,cobbled_deepslate,deepslate,tuff,dirt,granite,diorite,andesite,netherrack,blackstone,basalt";
|
c.trashItems = "cobblestone,cobbled_deepslate,deepslate,tuff,dirt,granite,diorite,andesite,netherrack,blackstone,basalt";
|
||||||
}
|
}
|
||||||
|
if (c.scaffoldBlocks == null || c.scaffoldBlocks.isBlank()) {
|
||||||
|
c.scaffoldBlocks = "cobblestone,cobbled_deepslate,deepslate,netherrack,dirt,granite,diorite,andesite,tuff,blackstone,basalt";
|
||||||
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,13 @@ public class DigConfig {
|
|||||||
/** 优先绕开岩浆池(给岩浆方块额外寻路代价) */
|
/** 优先绕开岩浆池(给岩浆方块额外寻路代价) */
|
||||||
public boolean avoidLava = true;
|
public boolean avoidLava = true;
|
||||||
|
|
||||||
|
// ---- 搭路/放置 ----
|
||||||
|
/** 允许 Baritone 放置方块:没有路(深渊/缺口/岩浆挡路)时自动搭桥、垫脚 */
|
||||||
|
public boolean allowPlace = true;
|
||||||
|
/** 搭路方块清单(逗号分隔的物品 id,带不带 "minecraft:" 前缀均可);
|
||||||
|
* 会自动从背包挪一组到快捷栏供 Baritone 放置,同时喂给 Baritone 作为可放置物品 */
|
||||||
|
public String scaffoldBlocks = "cobblestone,cobbled_deepslate,deepslate,netherrack,dirt,granite,diorite,andesite,tuff,blackstone,basalt";
|
||||||
|
|
||||||
// ---- 杀戮光环 ----
|
// ---- 杀戮光环 ----
|
||||||
/** 杀戮光环:自动攻击附近敌对生物 */
|
/** 杀戮光环:自动攻击附近敌对生物 */
|
||||||
public boolean killAura = false;
|
public boolean killAura = false;
|
||||||
@@ -98,6 +105,11 @@ public class DigConfig {
|
|||||||
return parseOreList(this.trashItems);
|
return parseOreList(this.trashItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取搭路方块清单 */
|
||||||
|
public List<String> getScaffoldItemList() {
|
||||||
|
return parseOreList(this.scaffoldBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> parseOreList(String str) {
|
private static List<String> parseOreList(String str) {
|
||||||
if (str == null || str.isBlank()) {
|
if (str == null || str.isBlank()) {
|
||||||
return List.of();
|
return List.of();
|
||||||
@@ -125,6 +137,8 @@ public class DigConfig {
|
|||||||
c.trashItems = this.trashItems;
|
c.trashItems = this.trashItems;
|
||||||
c.trashReserve = this.trashReserve;
|
c.trashReserve = this.trashReserve;
|
||||||
c.avoidLava = this.avoidLava;
|
c.avoidLava = this.avoidLava;
|
||||||
|
c.allowPlace = this.allowPlace;
|
||||||
|
c.scaffoldBlocks = this.scaffoldBlocks;
|
||||||
c.killAura = this.killAura;
|
c.killAura = this.killAura;
|
||||||
c.killAuraSafe = this.killAuraSafe;
|
c.killAuraSafe = this.killAuraSafe;
|
||||||
c.killRange = this.killRange;
|
c.killRange = this.killRange;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import autodig.client.miner.NetherMiner;
|
|||||||
import autodig.client.miner.OverworldMiner;
|
import autodig.client.miner.OverworldMiner;
|
||||||
import autodig.client.service.AutoEat;
|
import autodig.client.service.AutoEat;
|
||||||
import autodig.client.service.AutoGear;
|
import autodig.client.service.AutoGear;
|
||||||
|
import autodig.client.service.AutoScaffold;
|
||||||
import autodig.client.service.AutoTrash;
|
import autodig.client.service.AutoTrash;
|
||||||
import autodig.client.service.DeathRecorder;
|
import autodig.client.service.DeathRecorder;
|
||||||
import autodig.client.service.KillAura;
|
import autodig.client.service.KillAura;
|
||||||
@@ -35,6 +36,7 @@ public final class DigController {
|
|||||||
private final KillAura killAura = new KillAura();
|
private final KillAura killAura = new KillAura();
|
||||||
private final AutoGear autoGear = new AutoGear();
|
private final AutoGear autoGear = new AutoGear();
|
||||||
private final AutoTrash autoTrash = new AutoTrash();
|
private final AutoTrash autoTrash = new AutoTrash();
|
||||||
|
private final AutoScaffold autoScaffold = new AutoScaffold();
|
||||||
private final DeathRecorder deathRecorder = new DeathRecorder();
|
private final DeathRecorder deathRecorder = new DeathRecorder();
|
||||||
private final SessionStats stats = new SessionStats();
|
private final SessionStats stats = new SessionStats();
|
||||||
private final OverworldMiner overworld = new OverworldMiner(this.bridge);
|
private final OverworldMiner overworld = new OverworldMiner(this.bridge);
|
||||||
@@ -60,10 +62,11 @@ public final class DigController {
|
|||||||
}
|
}
|
||||||
PlayerEntity player = client.player;
|
PlayerEntity player = client.player;
|
||||||
|
|
||||||
// 常驻能力:杀戮光环、自动进食、背包满丢垃圾、换装冷却
|
// 常驻能力:杀戮光环、自动进食、背包满丢垃圾、搭路方块补给、换装冷却
|
||||||
this.killAura.tick(config);
|
this.killAura.tick(config);
|
||||||
this.autoEat.tick(config);
|
this.autoEat.tick(config);
|
||||||
this.autoTrash.tick(config);
|
this.autoTrash.tick(config);
|
||||||
|
this.autoScaffold.tick(config);
|
||||||
this.autoGear.tick();
|
this.autoGear.tick();
|
||||||
|
|
||||||
// 死亡处理:记录死亡次数,暂停任务,重生后按需回到死亡坐标
|
// 死亡处理:记录死亡次数,暂停任务,重生后按需回到死亡坐标
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public final class AutoDigGui extends Screen {
|
|||||||
private TextFieldWidget overworldOresField;
|
private TextFieldWidget overworldOresField;
|
||||||
private TextFieldWidget netherOresField;
|
private TextFieldWidget netherOresField;
|
||||||
private TextFieldWidget trashField;
|
private TextFieldWidget trashField;
|
||||||
|
private TextFieldWidget scaffoldField;
|
||||||
|
|
||||||
public AutoDigGui(AutoDigModClient mod) {
|
public AutoDigGui(AutoDigModClient mod) {
|
||||||
super(Text.literal("AutoDig"));
|
super(Text.literal("AutoDig"));
|
||||||
@@ -75,6 +76,7 @@ public final class AutoDigGui extends Screen {
|
|||||||
this.overworldOresField = null;
|
this.overworldOresField = null;
|
||||||
this.netherOresField = null;
|
this.netherOresField = null;
|
||||||
this.trashField = null;
|
this.trashField = null;
|
||||||
|
this.scaffoldField = null;
|
||||||
|
|
||||||
// 面板宽度自适应窗口,最小 200 保证 +/- 与输入框可用
|
// 面板宽度自适应窗口,最小 200 保证 +/- 与输入框可用
|
||||||
this.panelW = MathHelper.clamp(this.width - 16, 200, 400);
|
this.panelW = MathHelper.clamp(this.width - 16, 200, 400);
|
||||||
@@ -120,6 +122,12 @@ public final class AutoDigGui extends Screen {
|
|||||||
this.config.autoTrash = v;
|
this.config.autoTrash = v;
|
||||||
this.init(); // 切换后显示/隐藏垃圾设置区
|
this.init(); // 切换后显示/隐藏垃圾设置区
|
||||||
});
|
});
|
||||||
|
y = this.checkPair(y, "允许搭方块(无路时自动放置)", () -> this.config.allowPlace, v -> {
|
||||||
|
this.syncFields(); // 保留输入框中未应用的编辑
|
||||||
|
this.config.allowPlace = v;
|
||||||
|
this.init(); // 切换后显示/隐藏搭路设置区
|
||||||
|
},
|
||||||
|
null, null, null);
|
||||||
y += 10;
|
y += 10;
|
||||||
|
|
||||||
y = this.header(y, "进食/保命/攻击阈值");
|
y = this.header(y, "进食/保命/攻击阈值");
|
||||||
@@ -149,6 +157,13 @@ public final class AutoDigGui extends Screen {
|
|||||||
y += 10;
|
y += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.config.allowPlace) {
|
||||||
|
y = this.header(y, "搭路方块设置(无路时自动放置)");
|
||||||
|
y = this.fieldRow(y, "搭路方块(逗号分隔,自动补进快捷栏)",
|
||||||
|
this.config.scaffoldBlocks, tf -> this.scaffoldField = tf);
|
||||||
|
y += 10;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.config.task == MineTask.OVERWORLD) {
|
if (this.config.task == MineTask.OVERWORLD) {
|
||||||
y = this.header(y, "主世界设置");
|
y = this.header(y, "主世界设置");
|
||||||
y = this.numberRow(y, "挖掘层 (Y)", () -> this.config.overworldLevel,
|
y = this.numberRow(y, "挖掘层 (Y)", () -> this.config.overworldLevel,
|
||||||
@@ -391,6 +406,9 @@ public final class AutoDigGui extends Screen {
|
|||||||
if (this.trashField != null) {
|
if (this.trashField != null) {
|
||||||
this.config.trashItems = this.trashField.getText();
|
this.config.trashItems = this.trashField.getText();
|
||||||
}
|
}
|
||||||
|
if (this.scaffoldField != null) {
|
||||||
|
this.config.scaffoldBlocks = this.scaffoldField.getText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 把界面临时配置写回 mod 全局配置并保存(供 controller 实时读取)。 */
|
/** 把界面临时配置写回 mod 全局配置并保存(供 controller 实时读取)。 */
|
||||||
@@ -399,6 +417,8 @@ public final class AutoDigGui extends Screen {
|
|||||||
target.task = this.config.task;
|
target.task = this.config.task;
|
||||||
target.survivalFirst = this.config.survivalFirst;
|
target.survivalFirst = this.config.survivalFirst;
|
||||||
target.avoidLava = this.config.avoidLava;
|
target.avoidLava = this.config.avoidLava;
|
||||||
|
target.allowPlace = this.config.allowPlace;
|
||||||
|
target.scaffoldBlocks = this.config.scaffoldBlocks;
|
||||||
target.autoEat = this.config.autoEat;
|
target.autoEat = this.config.autoEat;
|
||||||
target.eatHungerThreshold = this.config.eatHungerThreshold;
|
target.eatHungerThreshold = this.config.eatHungerThreshold;
|
||||||
target.autoTool = this.config.autoTool;
|
target.autoTool = this.config.autoTool;
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package autodig.client.service;
|
||||||
|
|
||||||
|
import autodig.client.config.DigConfig;
|
||||||
|
import autodig.client.config.MineTask;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搭路方块补给服务。
|
||||||
|
*
|
||||||
|
* <p>Baritone 放置方块(无路时搭桥/垫脚)时从<strong>快捷栏</strong>挑选方块。
|
||||||
|
* 本服务在挖矿任务进行中周期性检查:快捷栏里搭路方块不足时,自动把主背包中
|
||||||
|
* 数量最多的一组搭路方块(按 {@code scaffoldBlocks} 清单)挪进快捷栏空位;
|
||||||
|
* 快捷栏已满时,只与快捷栏中已有的小堆搭路方块做整体交换,绝不碰工具、
|
||||||
|
* 食物等其他物品。操作走 {@code clickSlot} 正规网络包,单人/多人均可用。</p>
|
||||||
|
*
|
||||||
|
* <p>与 AutoTrash 协同:AutoTrash 丢弃垃圾时不会丢快捷栏物品,
|
||||||
|
* {@code trashReserve} 保留的方块正是搭路补给的来源。</p>
|
||||||
|
*/
|
||||||
|
public final class AutoScaffold {
|
||||||
|
|
||||||
|
/** 检查间隔(毫秒) */
|
||||||
|
private static final long CHECK_INTERVAL_MS = 2000;
|
||||||
|
/** 快捷栏搭路方块低于该数量时才补给 */
|
||||||
|
private static final int MIN_HOTBAR_COUNT = 16;
|
||||||
|
|
||||||
|
/** 上一次检查的时间戳(节流) */
|
||||||
|
private long lastCheck;
|
||||||
|
|
||||||
|
/** 每帧调用:快捷栏缺搭路方块时自动补给。 */
|
||||||
|
public void tick(DigConfig config) {
|
||||||
|
if (!config.allowPlace || config.task == MineTask.NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
if (client.player == null || client.interactionManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (client.currentScreen != null) {
|
||||||
|
return; // 有界面打开时不操作背包
|
||||||
|
}
|
||||||
|
PlayerEntity player = client.player;
|
||||||
|
ScreenHandler handler = player.currentScreenHandler;
|
||||||
|
if (handler != player.playerScreenHandler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!handler.getCursorStack().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now - this.lastCheck < CHECK_INTERVAL_MS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lastCheck = now;
|
||||||
|
|
||||||
|
Set<String> scaffold = new HashSet<>(config.getScaffoldItemList());
|
||||||
|
if (scaffold.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 快捷栏(main 0-8)已有的搭路方块总数
|
||||||
|
int hotbarCount = 0;
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
ItemStack s = player.getInventory().main.get(i);
|
||||||
|
if (!s.isEmpty() && isScaffold(s, scaffold)) {
|
||||||
|
hotbarCount += s.getCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hotbarCount >= MIN_HOTBAR_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 主背包(main 9-35)里找数量最多的一组搭路方块
|
||||||
|
int bestSlot = -1;
|
||||||
|
int bestCount = 0;
|
||||||
|
for (int i = 9; i < 36; i++) {
|
||||||
|
ItemStack s = player.getInventory().main.get(i);
|
||||||
|
if (!s.isEmpty() && isScaffold(s, scaffold) && s.getCount() > bestCount) {
|
||||||
|
bestCount = s.getCount();
|
||||||
|
bestSlot = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestSlot < 0) {
|
||||||
|
return; // 背包里没有搭路方块(trashReserve 为 0 或耗尽)
|
||||||
|
}
|
||||||
|
ItemStack bagStack = player.getInventory().main.get(bestSlot);
|
||||||
|
int bagScreenSlot = screenSlotOf(handler, bagStack);
|
||||||
|
if (bagScreenSlot < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 优先放进快捷栏空位(playerScreenHandler 槽位 36-44 对应快捷栏 0-8)
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
if (player.getInventory().main.get(i).isEmpty()) {
|
||||||
|
client.interactionManager.clickSlot(handler.syncId, bagScreenSlot, 0, SlotActionType.PICKUP, player);
|
||||||
|
client.interactionManager.clickSlot(handler.syncId, 36 + i, 0, SlotActionType.PICKUP, player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 无空位:只与快捷栏里已有的更小堆搭路方块整体交换,不碰其他物品
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
ItemStack s = player.getInventory().main.get(i);
|
||||||
|
if (!s.isEmpty() && isScaffold(s, scaffold) && s.getCount() < bagStack.getCount()) {
|
||||||
|
int hotScreenSlot = screenSlotOf(handler, s);
|
||||||
|
if (hotScreenSlot < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
client.interactionManager.clickSlot(handler.syncId, hotScreenSlot, 0, SlotActionType.PICKUP, player);
|
||||||
|
client.interactionManager.clickSlot(handler.syncId, bagScreenSlot, 0, SlotActionType.PICKUP, player);
|
||||||
|
client.interactionManager.clickSlot(handler.syncId, hotScreenSlot, 0, SlotActionType.PICKUP, player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 是否为清单内的搭路方块(BlockItem 且按 path 匹配,兼容命名空间前缀)。 */
|
||||||
|
private static boolean isScaffold(ItemStack stack, Set<String> scaffold) {
|
||||||
|
return stack.getItem() instanceof BlockItem
|
||||||
|
&& scaffold.contains(Registries.ITEM.getId(stack.getItem()).getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按对象引用在 ScreenHandler 里找槽位下标。 */
|
||||||
|
private static int screenSlotOf(ScreenHandler handler, ItemStack stack) {
|
||||||
|
for (int i = 0; i < handler.slots.size(); i++) {
|
||||||
|
if (handler.getSlot(i).getStack() == stack) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,8 @@ import net.minecraft.screen.slot.SlotActionType;
|
|||||||
*
|
*
|
||||||
* <p>背包接近满(已用格数达到阈值)时就主动把 {@code trashItems} 清单里的
|
* <p>背包接近满(已用格数达到阈值)时就主动把 {@code trashItems} 清单里的
|
||||||
* 垃圾物品丢出背包(圆石、凝灰岩、深板岩等挖掘副产物),为挖到的矿物提前
|
* 垃圾物品丢出背包(圆石、凝灰岩、深板岩等挖掘副产物),为挖到的矿物提前
|
||||||
* 腾出空间,避免背包彻底满后触发"背包已满需返回"而中断挖矿。方块类垃圾
|
* 腾出空间,避免背包彻底满后触发"背包已满需返回"而中断挖矿。<strong>快捷栏
|
||||||
|
* 物品永不自动丢弃</strong>(搭路方块/工具/食物常驻快捷栏)。方块类垃圾
|
||||||
* 保留 {@code trashReserve} 个供 Baritone 搭路/垫脚使用。丢弃通过
|
* 保留 {@code trashReserve} 个供 Baritone 搭路/垫脚使用。丢弃通过
|
||||||
* {@code clickSlot(THROW)} 走正规网络包,单人/多人均可用。</p>
|
* {@code clickSlot(THROW)} 走正规网络包,单人/多人均可用。</p>
|
||||||
*/
|
*/
|
||||||
@@ -62,9 +63,10 @@ public final class AutoTrash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 收集背包里的垃圾,按物品 id 分组(并记录是否为可放置的方块)
|
// 收集背包里的垃圾,按物品 id 分组(并记录是否为可放置的方块)
|
||||||
|
// 从 main 9-35 收集:快捷栏(main 0-8)物品永不自动丢弃(搭路方块/工具/食物)
|
||||||
Map<String, List<ItemStack>> groups = new HashMap<>();
|
Map<String, List<ItemStack>> groups = new HashMap<>();
|
||||||
Map<String, Boolean> blockLike = new HashMap<>();
|
Map<String, Boolean> blockLike = new HashMap<>();
|
||||||
for (int i = 0; i < 36; i++) {
|
for (int i = 9; i < 36; i++) {
|
||||||
ItemStack s = player.getInventory().main.get(i);
|
ItemStack s = player.getInventory().main.get(i);
|
||||||
if (s.isEmpty()) {
|
if (s.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "autodig",
|
"id": "autodig",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "AutoDig",
|
"name": "AutoDig",
|
||||||
"description": "自动挖矿模组(内置 Baritone 1.13.1,无需另行安装):主世界模式与下界模式,均可自定义目标矿物(带不带 minecraft: 前缀均可)。主世界鱼骨巷道挖矿 + 附近目标矿物自动绕道挖掘;下界自动进出传送门挖矿并支持返程。自动切换最适用工具(远古残骸等自动换钻石镐)、自动进食(避开特殊食物)、杀戮光环(不误伤中立生物)、保命优先、优先绕开岩浆、装备耐久保护(自动换备用装备)、背包近满提前丢垃圾防误判返程、死亡重生回点、实时状态 HUD。",
|
"description": "自动挖矿模组(内置 Baritone 1.13.1,无需另行安装):主世界模式与下界模式,均可自定义目标矿物(带不带 minecraft: 前缀均可)。主世界鱼骨巷道挖矿 + 附近目标矿物自动绕道挖掘;下界自动进出传送门挖矿并支持返程。无路时自动放置方块搭桥/垫脚(自动补给快捷栏搭路方块)、自动切换最适用工具(远古残骸等自动换钻石镐)、自动进食(避开特殊食物)、杀戮光环(不误伤中立生物)、保命优先、优先绕开岩浆、装备耐久保护(自动换备用装备)、背包近满提前丢垃圾防误判返程、死亡重生回点、实时状态 HUD。",
|
||||||
"authors": [],
|
"authors": [],
|
||||||
"contact": {},
|
"contact": {},
|
||||||
"license": "All-Rights-Reserved",
|
"license": "All-Rights-Reserved",
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户