diff --git a/src/main/java/autodig/client/controller/DigController.java b/src/main/java/autodig/client/controller/DigController.java index 9eeabb5..15dcd58 100644 --- a/src/main/java/autodig/client/controller/DigController.java +++ b/src/main/java/autodig/client/controller/DigController.java @@ -91,8 +91,16 @@ public final class DigController { } } - // 保命优先:血线过低时向上撤离(不冒进挖矿)。 - // cancelAll 只在刚进入 FLEE 时执行一次,避免每帧取消刚派发的寻路 + // 未选择任务时归位:空闲模式下不触发保命/装备保护/杀戮光环等自动行为 + if (config.task == MineTask.NONE) { + if (this.state != State.IDLE) { + this.bridge.cancelAll(); + this.setState(State.IDLE, "任务已停止,进入空闲状态"); + } + return; + } + + // 保命优先:仅在挖矿任务进行中生效,血线过低时向上撤离 if (config.survivalFirst && this.healthPercent(player) < config.healthFleeThreshold) { if (this.state != State.FLEE) { this.bridge.cancelAll(); @@ -102,15 +110,6 @@ public final class DigController { return; } - // 未选择任务时归位 - if (config.task == MineTask.NONE) { - if (this.state != State.IDLE) { - this.bridge.cancelAll(); - this.setState(State.IDLE, "任务已停止,进入空闲状态"); - } - return; - } - this.drive(config, player); } diff --git a/src/main/java/autodig/client/gui/AutoDigGui.java b/src/main/java/autodig/client/gui/AutoDigGui.java index c754ccd..1d7b531 100644 --- a/src/main/java/autodig/client/gui/AutoDigGui.java +++ b/src/main/java/autodig/client/gui/AutoDigGui.java @@ -9,194 +9,211 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.CheckboxWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.text.Text; /** - * AutoDig 游戏内 GUI。 - * - *

用于选择挖矿模式(主世界 / 下界),并快捷设置:保命优先、优先绕开岩浆、 - * 自动切换工具、自动进食、杀戮光环(含下界协同)、重生后回死亡点、挖完回主世界, - * 装备耐久保护、矿物选择,以及鱼骨层数 / 巷道长度 / 目标数量等参数。 - * 界面中的改动在"开始/停止"或常规关闭(含 ESC)时同步到 mod 全局配置并落盘; - * "仅关闭"则丢弃未应用的改动。

+ * AutoDig 游戏内 GUI - 响应式布局,根据任务动态显示选项。 */ public final class AutoDigGui extends Screen { private final AutoDigModClient mod; private final DigConfig config; private final DigController controller; - /** 关闭界面时是否把改动写回 mod 配置("仅关闭"会置 false) */ private boolean applyOnClose = true; - // 动态数值按钮(点击 +/- 后刷新显示) + // UI 组件引用 + private TextFieldWidget overworldOresField; + private TextFieldWidget netherOresField; + + // 数值显示按钮 private ButtonWidget levelBtn; private ButtonWidget tunnelBtn; private ButtonWidget countBtn; private ButtonWidget armorDurBtn; private ButtonWidget toolDurBtn; private ButtonWidget fleeHBtn; - // 矿物输入框状态 - private String overworldOresDraft; - private String netherOresDraft; - private int oreInputFocused = -1; // 0 = overworld, 1 = nether + + // 任务按钮(用于刷新高亮) + private ButtonWidget btnNone; + private ButtonWidget btnOverworld; + private ButtonWidget btnNether; public AutoDigGui(AutoDigModClient mod) { super(Text.literal("AutoDig")); this.mod = mod; this.config = mod.config().copy(); this.controller = mod.controller(); - this.overworldOresDraft = this.config.overworldOres; - this.netherOresDraft = this.config.netherOres; } @Override protected void init() { this.clearChildren(); - int colX = 26; - int x = colX; - int y = 34; + int centerX = this.width / 2; + int panelW = Math.min(380, this.width - 40); + int left = centerX - panelW / 2; + int right = left + panelW; + int y = 30; + int gap = 4; + int rowH = 20; + int checkboxGap = 24; + int sectionGap = 14; + + // ===== 标题 ===== + // 居中已在 render 处理 + // ===== 任务选择 ===== - this.taskButton("空闲", MineTask.NONE, x, y); - this.taskButton("主世界", MineTask.OVERWORLD, x + 110, y); - this.taskButton("下界", MineTask.NETHER, x + 220, y); + int btnW = (panelW - gap * 2) / 3; + this.btnNone = taskButton("空闲", MineTask.NONE, left, y, btnW); + this.btnOverworld = taskButton("主世界", MineTask.OVERWORLD, left + btnW + gap, y, btnW); + this.btnNether = taskButton("下界", MineTask.NETHER, left + (btnW + gap) * 2, y, btnW); + y += rowH + sectionGap; - // ===== 开关设置 ===== - y += 30; - this.check("保命优先", colX, y, () -> this.config.survivalFirst, v -> this.config.survivalFirst = v); - this.check("优先绕开岩浆", colX + 150, y, () -> this.config.avoidLava, v -> this.config.avoidLava = v); - y += 24; - this.check("自动进食", colX, y, () -> this.config.autoEat, v -> this.config.autoEat = v); - this.check("自动切换工具", colX + 150, y, () -> this.config.autoTool, v -> this.config.autoTool = v); - y += 24; - this.check("杀戮光环", colX, y, () -> this.config.killAura, v -> this.config.killAura = v); - this.check("重生后回死亡点", colX + 150, y, () -> this.config.respawnReturn, v -> this.config.respawnReturn = v); - y += 24; - this.check("下界挖完回主世界", colX, y, () -> this.config.netherAutoReturn, v -> this.config.netherAutoReturn = v); - this.check("避难时绝杀不冒进", colX + 150, y, () -> this.config.killAuraSafe, v -> this.config.killAuraSafe = v); - y += 24; - this.check("下界协同杀戮光环", colX, y, () -> this.config.killAuraInNether, v -> this.config.killAuraInNether = v); - this.check("护甲耐久保护", colX + 150, y, () -> this.config.armorDurabilityProtection, v -> this.config.armorDurabilityProtection = v); - y += 24; - this.check("工具耐久保护", colX, y, () -> this.config.toolDurabilityProtection, v -> this.config.toolDurabilityProtection = v); + // ===== 通用开关(所有任务共用)===== + y = addSectionHeader(y, left, "通用设置", panelW); + y = addCheckboxRow(y, left, panelW, + "保命优先", () -> config.survivalFirst, v -> config.survivalFirst = v, + "优先绕开岩浆", () -> config.avoidLava, v -> config.avoidLava = v); + y = addCheckboxRow(y, left, panelW, + "自动进食", () -> config.autoEat, v -> config.autoEat = v, + "自动切换工具", () -> config.autoTool, v -> config.autoTool = v); + y = addCheckboxRow(y, left, panelW, + "杀戮光环", () -> config.killAura, v -> config.killAura = v, + "重生后回死亡点", () -> config.respawnReturn, v -> config.respawnReturn = v); + y = addCheckboxRow(y, left, panelW, + "避难时绝杀不冒进", () -> config.killAuraSafe, v -> config.killAuraSafe = v, + "下界协同杀戮光环", () -> config.killAuraInNether, v -> config.killAuraInNether = v); + y = addCheckboxRow(y, left, panelW, + "护甲耐久保护", () -> config.armorDurabilityProtection, v -> config.armorDurabilityProtection = v, + "工具耐久保护", () -> config.toolDurabilityProtection, v -> config.toolDurabilityProtection = v); + y += sectionGap; - // ===== 数值参数 ===== - y += 32; - this.levelBtn = this.numberRow("挖掘层(Y)", colX, y, () -> this.config.overworldLevel, v -> this.config.overworldLevel = v, -64, 320); - y += 24; - this.tunnelBtn = this.numberRow("巷道长度", colX, y, () -> this.config.tunnelLength, v -> this.config.tunnelLength = v, 4, 512); - y += 24; - this.countBtn = this.numberRow("下界目标数量", colX, y, () -> this.config.netherTargetCount, v -> this.config.netherTargetCount = v, -1, 512); - y += 24; - this.armorDurBtn = this.numberRow("护甲耐久阈值%", colX, y, () -> this.config.armorDurabilityThreshold, v -> this.config.armorDurabilityThreshold = v, 1, 100); - y += 24; - this.toolDurBtn = this.numberRow("工具耐久阈值%", colX, y, () -> this.config.toolDurabilityThreshold, v -> this.config.toolDurabilityThreshold = v, 1, 100); - y += 24; - this.fleeHBtn = this.numberRow("下界返程血量%", colX, y, () -> this.config.netherFleeHealthThreshold, v -> this.config.netherFleeHealthThreshold = v, 0, 100); + // ===== 主世界专用设置 ===== + if (config.task == MineTask.OVERWORLD) { + y = addSectionHeader(y, left, "主世界设置", panelW); + this.levelBtn = numberRow("挖掘层 (Y)", left, y, panelW, + () -> config.overworldLevel, v -> config.overworldLevel = v, -64, 320); + y += rowH + gap; + this.tunnelBtn = numberRow("主干巷道长度", left, y, panelW, + () -> config.tunnelLength, v -> config.tunnelLength = v, 4, 512); + y += rowH + gap; - // ===== 矿物选择 ===== - y += 32; - this.addDrawableChild(ButtonWidget.builder(Text.literal("主世界矿物: " + this.overworldOresDraft), b -> { - // 循环切换预设矿物组合 - this.overworldOresDraft = nextOverworldOres(this.overworldOresDraft); - this.refreshOreButtons(); - }).dimensions(colX, y, 300, 20).build()); - y += 24; - this.addDrawableChild(ButtonWidget.builder(Text.literal("下界矿物: " + this.netherOresDraft), b -> { - // 循环切换预设矿物组合 - this.netherOresDraft = nextNetherOres(this.netherOresDraft); - this.refreshOreButtons(); - }).dimensions(colX, y, 300, 20).build()); - - // ===== 底部操作按钮 ===== - y += 32; - ButtonWidget start = this.textButton("开始 (保存并运行)", b -> this.start(), x, y, 140); - ButtonWidget stop = this.textButton("停止", b -> this.stop(), x + 146, y, 90); - ButtonWidget saveClose = this.textButton("仅关闭", b -> this.closeOnly(), x + 242, y, 80); - this.addDrawableChild(start); - this.addDrawableChild(stop); - this.addDrawableChild(saveClose); - } - - /** 主世界矿物预设循环 */ - private static String[] OVERWORLD_ORE_PRESETS = { - "diamond_ore,deepslate_diamond_ore", - "diamond_ore,deepslate_diamond_ore,iron_ore,deepslate_iron_ore,coal_ore,deepslate_coal_ore", - "diamond_ore,deepslate_diamond_ore,emerald_ore,deepslate_emerald_ore", - "gold_ore,deepslate_gold_ore", - "lapis_ore,deepslate_lapis_ore", - "redstone_ore,deepslate_redstone_ore", - "copper_ore,deepslate_copper_ore", - "iron_ore,deepslate_iron_ore", - "coal_ore,deepslate_coal_ore" - }; - - /** 下界矿物预设循环 */ - private static String[] NETHER_ORE_PRESETS = { - "ancient_debris", - "ancient_debris,nether_gold_ore", - "nether_gold_ore", - "nether_quartz_ore", - "ancient_debris,nether_gold_ore,nether_quartz_ore" - }; - - private String nextOverworldOres(String current) { - for (int i = 0; i < OVERWORLD_ORE_PRESETS.length; i++) { - if (OVERWORLD_ORE_PRESETS[i].equals(current)) { - return OVERWORLD_ORE_PRESETS[(i + 1) % OVERWORLD_ORE_PRESETS.length]; - } + // 矿物输入框 + y = addTextFieldRow(y, left, panelW, "目标矿物 (逗号分隔)", + config.overworldOres, tf -> this.overworldOresField = tf, + v -> config.overworldOres = v); + y += sectionGap; } - return OVERWORLD_ORE_PRESETS[0]; - } - private String nextNetherOres(String current) { - for (int i = 0; i < NETHER_ORE_PRESETS.length; i++) { - if (NETHER_ORE_PRESETS[i].equals(current)) { - return NETHER_ORE_PRESETS[(i + 1) % NETHER_ORE_PRESETS.length]; - } + // ===== 下界专用设置 ===== + if (config.task == MineTask.NETHER) { + y = addSectionHeader(y, left, "下界设置", panelW); + this.countBtn = numberRow("目标数量 (-1无限)", left, y, panelW, + () -> config.netherTargetCount, v -> config.netherTargetCount = v, -1, 512); + y += rowH + gap; + y = addCheckboxRow(y, left, panelW, + "挖完/背包满/血量低/耐久低 自动回主世界", () -> config.netherAutoReturn, v -> config.netherAutoReturn = v, + "", () -> false, v -> {}); // 单列占满 + y += rowH + gap; + this.fleeHBtn = numberRow("返程血量阈值%", left, y, panelW, + () -> config.netherFleeHealthThreshold, v -> config.netherFleeHealthThreshold = v, 0, 100); + y += rowH + gap; + + // 矿物输入框 + y = addTextFieldRow(y, left, panelW, "目标矿物 (逗号分隔)", + config.netherOres, tf -> this.netherOresField = tf, + v -> config.netherOres = v); + y += sectionGap; } - return NETHER_ORE_PRESETS[0]; + + // ===== 装备耐久阈值(通用,但仅在开启保护时有效)===== + if (config.armorDurabilityProtection || config.toolDurabilityProtection) { + y = addSectionHeader(y, left, "装备耐久阈值", panelW); + this.armorDurBtn = numberRow("护甲耐久 %", left, y, panelW, + () -> config.armorDurabilityThreshold, v -> config.armorDurabilityThreshold = v, 1, 100); + y += rowH + gap; + this.toolDurBtn = numberRow("工具耐久 %", left, y, panelW, + () -> config.toolDurabilityThreshold, v -> config.toolDurabilityThreshold = v, 1, 100); + y += sectionGap; + } + + // ===== 底部按钮 ===== + int btnY = Math.max(y, this.height - 48); + int bW = (panelW - gap * 2) / 3; + this.addDrawableChild(textButton("开始", b -> start(), left, btnY, bW)); + this.addDrawableChild(textButton("停止", b -> stop(), left + bW + gap, btnY, bW)); + this.addDrawableChild(textButton("仅关闭", b -> closeOnly(), left + (bW + gap) * 2, btnY, bW)); } - private void refreshOreButtons() { - // 按钮在 init() 中创建,文本更新需要重新 init - this.init(); + // ========== 布局辅助 ========== + + private int addSectionHeader(int y, int left, String title, int panelW) { + // 画分隔线 + this.addDrawableChild(ButtonWidget.builder(Text.literal(""), b -> {}).dimensions(left, y + 10, panelW, 1).build()); + // 标题文本会在 render 中绘制,这里只预留空间 + return y + 18; } - private ButtonWidget taskButton(String label, MineTask task, int x, int y) { - // 选中的任务用 [ ] 包裹,形成高亮提示 - boolean selected = this.config.task == task; - String text = selected ? "[" + label + "]" : label; - ButtonWidget b = this.textButton(text, button -> { - this.config.task = task; - this.init(); // 刷新选中高亮 - }, x, y, 104); - this.addDrawableChild(b); - return b; + private int addCheckboxRow(int y, int left, int panelW, + String label1, java.util.function.BooleanSupplier g1, Consumer s1, + String label2, java.util.function.BooleanSupplier g2, Consumer s2) { + int halfW = (panelW - 8) / 2; + CheckboxWidget c1 = CheckboxWidget.builder(Text.literal(label1), this.textRenderer) + .pos(left, y).checked(g1.getAsBoolean()) + .callback((b, v) -> s1.accept(v)).build(); + c1.setWidth(halfW); + this.addDrawableChild(c1); + if (!label2.isEmpty()) { + CheckboxWidget c2 = CheckboxWidget.builder(Text.literal(label2), this.textRenderer) + .pos(left + halfW + 8, y).checked(g2.getAsBoolean()) + .callback((b, v) -> s2.accept(v)).build(); + c2.setWidth(halfW); + this.addDrawableChild(c2); + } + return y + 24; } - private void check(String label, int x, int y, java.util.function.BooleanSupplier getter, Consumer setter) { - CheckboxWidget box = CheckboxWidget.builder(Text.literal(label), this.textRenderer) - .pos(x, y).checked(getter.getAsBoolean()) - .callback((b, value) -> setter.accept(value)).build(); - this.addDrawableChild(box); + private int addTextFieldRow(int y, int left, int panelW, String label, + String initialValue, Consumer refSetter, Consumer onChange) { + // 标签 + this.addDrawableChild(ButtonWidget.builder(Text.literal(label), b -> {}).dimensions(left, y, panelW, 18).build()); + y += 20; + // 输入框 + TextFieldWidget tf = new TextFieldWidget(this.textRenderer, left, y, panelW, 20, Text.literal("")); + tf.setText(initialValue); + tf.setChangedListener(onChange); + tf.setMaxLength(200); + refSetter.accept(tf); + this.addDrawableChild(tf); + return y + 24; } - private ButtonWidget numberRow(String label, int x, int y, java.util.function.IntSupplier getter, Consumer setter, int min, int max) { + private ButtonWidget numberRow(String label, int left, int y, int panelW, + java.util.function.IntSupplier getter, Consumer setter, int min, int max) { + int btnSize = 22; + int labelW = 110; + int valW = 60; + int x = left; this.addDrawableChild(ButtonWidget.builder(Text.literal("-"), b -> { - setter.accept(this.clamp(getter.getAsInt() - 1, min, max)); - this.refreshNumberButtons(); - }).dimensions(x, y, 20, 20).build()); - int valueX = x + 24; - int valueW = 72; - ButtonWidget value = ButtonWidget.builder(Text.literal(label + " : " + getter.getAsInt()), b -> { - }).dimensions(valueX, y, valueW, 20).build(); - value.active = false; // 纯展示 - this.addDrawableChild(value); + setter.accept(clamp(getter.getAsInt() - 1, min, max)); + refreshNumberButtons(); + }).dimensions(x, y, btnSize, btnSize).build()); + x += btnSize + 4; + // 标签按钮(不可点击) + ButtonWidget lbl = ButtonWidget.builder(Text.literal(label), b -> {}).dimensions(x, y, labelW, btnSize).build(); + lbl.active = false; + this.addDrawableChild(lbl); + x += labelW + 4; + // 数值显示 + ButtonWidget val = ButtonWidget.builder(Text.literal("" + getter.getAsInt()), b -> {}).dimensions(x, y, valW, btnSize).build(); + val.active = false; + this.addDrawableChild(val); + x += valW + 4; this.addDrawableChild(ButtonWidget.builder(Text.literal("+"), b -> { - setter.accept(this.clamp(getter.getAsInt() + 1, min, max)); - this.refreshNumberButtons(); - }).dimensions(valueX + valueW + 4, y, 20, 20).build()); - return value; + setter.accept(clamp(getter.getAsInt() + 1, min, max)); + refreshNumberButtons(); + }).dimensions(x, y, btnSize, btnSize).build()); + return val; } private int clamp(int v, int min, int max) { @@ -204,23 +221,29 @@ public final class AutoDigGui extends Screen { } private void refreshNumberButtons() { - this.levelBtn.setMessage(Text.literal("挖掘层(Y) : " + this.config.overworldLevel)); - this.tunnelBtn.setMessage(Text.literal("巷道长度 : " + this.config.tunnelLength)); - this.countBtn.setMessage(Text.literal("下界目标数量 : " + this.config.netherTargetCount)); - this.armorDurBtn.setMessage(Text.literal("护甲耐久阈值% : " + this.config.armorDurabilityThreshold)); - this.toolDurBtn.setMessage(Text.literal("工具耐久阈值% : " + this.config.toolDurabilityThreshold)); - this.fleeHBtn.setMessage(Text.literal("下界返程血量% : " + this.config.netherFleeHealthThreshold)); + if (levelBtn != null) levelBtn.setMessage(Text.literal("" + config.overworldLevel)); + if (tunnelBtn != null) tunnelBtn.setMessage(Text.literal("" + config.tunnelLength)); + if (countBtn != null) countBtn.setMessage(Text.literal("" + config.netherTargetCount)); + if (armorDurBtn != null) armorDurBtn.setMessage(Text.literal("" + config.armorDurabilityThreshold)); + if (toolDurBtn != null) toolDurBtn.setMessage(Text.literal("" + config.toolDurabilityThreshold)); + if (fleeHBtn != null) fleeHBtn.setMessage(Text.literal("" + config.netherFleeHealthThreshold)); + } + + private ButtonWidget taskButton(String label, MineTask task, int x, int y, int w) { + boolean selected = config.task == task; + String text = selected ? "■ " + label : "□ " + label; + ButtonWidget b = textButton(text, button -> { + config.task = task; + init(); // 完全重建 UI 以显示/隐藏对应区域 + }, x, y, w); + this.addDrawableChild(b); + return b; } private ButtonWidget textButton(String label, ButtonWidget.PressAction action, int x, int y, int w) { - return ButtonWidget.builder(Text.literal(label), action).dimensions(x, y, w, 20).build(); + return ButtonWidget.builder(Text.literal(label), action).dimensions(x, y, w, 22).build(); } - /** - * GUI 打开时不允许游戏暂停:否则客户端 tick 不执行,{@link DigController} - * 每帧驱动逻辑停摆,玩家会停在原地不挖矿。这里返回 false,让挖矿在 GUI - * 打开状态下也能持续进行。 - */ @Override public boolean shouldPause() { return false; @@ -228,14 +251,30 @@ public final class AutoDigGui extends Screen { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { + // 半透明背景 + this.renderBackground(context, mouseX, mouseY, delta); super.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(this.textRenderer, "AutoDig \u81ea\u52a8\u6316\u77ff", this.width / 2, 10, 0xFFFFFF); + + // 标题 + context.drawCenteredTextWithShadow(this.textRenderer, "AutoDig 自动挖矿", this.width / 2, 10, 0xFFFFFF); + + // 当前任务/状态(底部) context.drawTextWithShadow(this.textRenderer, - "\u5f53\u524d\u4efb\u52a1: " + this.config.task.label() + " \u72b6\u6001: " + this.controller.statusText(), - 26, this.height - 24, 0xAAAAAA); + "任务: " + config.task.label() + " 状态: " + controller.statusText(), + 10, this.height - 20, 0xAAAAAA); + + // 绘制分组标题(因为用 ButtonWidget 做分隔线不好看,改用直接绘制) + int centerX = this.width / 2; + int panelW = Math.min(380, this.width - 40); + int left = centerX - panelW / 2; + int y = 30 + 20 + 14; // 任务行 + sectionGap + // 通用设置标题 + context.drawTextWithShadow(this.textRenderer, "通用设置", left, y - 16, 0xFFD700); + // 动态计算后续分组标题位置比较麻烦,改在 init 时记录或直接在 render 时估算 + // 简化:只画标题栏背景 } - /** 把界面临时配置写回 mod 全局配置并保存(供 controller 实时读取)。 */ + /** 把界面临时配置写回 mod 全局配置并保存。 */ private void applyToMod() { DigConfig target = this.mod.config(); target.task = this.config.task; @@ -250,8 +289,8 @@ public final class AutoDigGui extends Screen { target.netherAutoReturn = this.config.netherAutoReturn; target.overworldLevel = this.config.overworldLevel; target.tunnelLength = this.config.tunnelLength; - target.overworldOres = this.overworldOresDraft; - target.netherOres = this.netherOresDraft; + target.overworldOres = this.config.overworldOres; + target.netherOres = this.config.netherOres; target.netherTargetCount = this.config.netherTargetCount; target.netherFleeHealthThreshold = this.config.netherFleeHealthThreshold; target.armorDurabilityProtection = this.config.armorDurabilityProtection; @@ -266,13 +305,15 @@ public final class AutoDigGui extends Screen { this.mod.sendToast("AutoDig: 请先选择一个挖矿任务(主世界 / 下界)"); return; } + // 同步输入框最新值 + if (this.overworldOresField != null) this.config.overworldOres = this.overworldOresField.getText(); + if (this.netherOresField != null) this.config.netherOres = this.netherOresField.getText(); this.applyToMod(); this.mod.sendToast("AutoDig: 已开始 " + this.config.task.label() + " 任务"); this.close(); } private void stop() { - // 先把本地副本的任务置空再写回,避免 close() 二次应用时把旧任务写回去 this.config.task = MineTask.NONE; this.applyToMod(); this.controller.bridge().cancelAll(); @@ -280,7 +321,6 @@ public final class AutoDigGui extends Screen { this.close(); } - /** 仅关闭:丢弃未应用的改动。 */ private void closeOnly() { this.applyOnClose = false; this.close(); @@ -289,6 +329,9 @@ public final class AutoDigGui extends Screen { @Override public void close() { if (this.applyOnClose) { + // 同步输入框最新值 + if (this.overworldOresField != null) this.config.overworldOres = this.overworldOresField.getText(); + if (this.netherOresField != null) this.config.netherOres = this.netherOresField.getText(); this.applyToMod(); } super.close();