From 74356da7787767098f964f57dabcd6087205dd10 Mon Sep 17 00:00:00 2001 From: uxmlen <38371923+uxmlen@users.noreply.github.com> Date: Tue, 6 May 2025 23:12:17 +0300 Subject: [PATCH 1/5] feat: add fuel amount setting --- .../systems/modules/world/AutoSmelter.java | 41 ++++++++-- .../meteorclient/utils/player/InvUtils.java | 78 +++++++++++++++++-- 2 files changed, 106 insertions(+), 13 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index 80c600eeeb..0cbb9c2022 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -6,10 +6,7 @@ package meteordevelopment.meteorclient.systems.modules.world; import meteordevelopment.meteorclient.mixininterface.IAbstractFurnaceScreenHandler; -import meteordevelopment.meteorclient.settings.BoolSetting; -import meteordevelopment.meteorclient.settings.ItemListSetting; -import meteordevelopment.meteorclient.settings.Setting; -import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.Utils; @@ -50,6 +47,15 @@ public class AutoSmelter extends Module { .build() ); + private final Setting fuelAmount = sgGeneral.add(new IntSetting.Builder() + .name("fuel-amount") + .description("Amount of fuel to insert in each furnace (1-64).") + .defaultValue(32) + .range(1, 64) + .sliderMax(64) + .build() + ); + public AutoSmelter() { super(Categories.World, "auto-smelter", "Automatically smelts items from your inventory"); } @@ -78,6 +84,12 @@ public void tick(AbstractFurnaceScreenHandler c) { insertItems(c); } + /** + * Checks and refills the fuel slot in the furnace. + * Will add fuel up to the specified fuel amount setting. + * + * @param c The furnace screen handler + */ private void insertItems(AbstractFurnaceScreenHandler c) { ItemStack inputItemStack = c.slots.getFirst().getStack(); if (!inputItemStack.isEmpty()) return; @@ -103,12 +115,25 @@ private void insertItems(AbstractFurnaceScreenHandler c) { InvUtils.move().fromId(slot).toId(0); } + /** + * Checks and refills the fuel slot in the furnace. + * + * @param c The furnace screen handler + */ private void checkFuel(AbstractFurnaceScreenHandler c) { ItemStack fuelStack = c.slots.get(1).getStack(); + // If the furnace is burning, don't do anything if (c.getFuelProgress() > 0) return; if (!fuelStack.isEmpty()) return; + // Check if we already have the maximum amount of fuel + if (!fuelStack.isEmpty() && fuelStack.getCount() >= fuelAmount.get()) return; + + // Calculate how much more fuel we need + int neededFuelCount = fuelStack.isEmpty() ? fuelAmount.get() : fuelAmount.get() - fuelStack.getCount(); + + // Find fuel in inventory int slot = -1; for (int i = 3; i < c.slots.size(); i++) { ItemStack item = c.slots.get(i).getStack(); @@ -125,9 +150,15 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { return; } - InvUtils.move().fromId(slot).toId(1); + InvUtils.move(neededFuelCount).fromId(slot).toId(1); } + /** + * Takes the smelted results from the furnace output slot. + * Disables the module if inventory is full and can't take results. + * + * @param c The furnace screen handler + */ private void takeResults(AbstractFurnaceScreenHandler c) { ItemStack resultStack = c.slots.get(2).getStack(); if (resultStack.isEmpty()) return; diff --git a/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java b/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java index 2d42abf874..ef1d1a288c 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/player/InvUtils.java @@ -176,6 +176,18 @@ public static Action move() { return ACTION; } + /** + * Moves a specific number of items between inventory slots. + * Useful for moving partial stacks. + * + * @param count The maximum number of items to move + * @return An Action object configured for moving the specified number of items + */ + public static Action move(int count) { + ACTION.count = count; + return move(); + } + public static Action click() { ACTION.type = SlotActionType.PICKUP; return ACTION; @@ -202,7 +214,8 @@ public static Action drop() { } public static void dropHand() { - if (!mc.player.currentScreenHandler.getCursorStack().isEmpty()) mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, ScreenHandler.EMPTY_SPACE_SLOT_INDEX, 0, SlotActionType.PICKUP, mc.player); + if (!mc.player.currentScreenHandler.getCursorStack().isEmpty()) + mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, ScreenHandler.EMPTY_SPACE_SLOT_INDEX, 0, SlotActionType.PICKUP, mc.player); } public static class Action { @@ -211,6 +224,8 @@ public static class Action { private int from = -1; private int to = -1; private int data = 0; + // Default to moving all items + private int count = Integer.MAX_VALUE; private boolean isRecursive = false; @@ -309,8 +324,13 @@ private void run() { } if (type != null && from != -1 && to != -1) { - click(from); - if (two) click(to); + if (type == SlotActionType.PICKUP && two && count < Integer.MAX_VALUE) { + // Use partial stack movement when count is specified + movePartialStack(); + } else { + click(from); + if (two) click(to); + } } SlotActionType preType = type; @@ -318,11 +338,7 @@ private void run() { int preFrom = from; int preTo = to; - type = null; - two = false; - from = -1; - to = -1; - data = 0; + resetActionState(); if (!isRecursive && hadEmptyCursor && preType == SlotActionType.PICKUP && preTwo && (preFrom != -1 && preTo != -1) && !mc.player.currentScreenHandler.getCursorStack().isEmpty()) { isRecursive = true; @@ -331,8 +347,54 @@ private void run() { } } + private void resetActionState() { + type = null; + two = false; + from = -1; + to = -1; + data = 0; + count = Integer.MAX_VALUE; + } + + /** + * Performs a click action on a specified slot ID in the current screen handler. + * Uses the current action type and data values for the click operation. + * + * @param id The ID of the slot to click on + */ private void click(int id) { mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, id, data, type, mc.player); } + + /** + * Moves a specific number of items from one slot to another. + */ + private void movePartialStack() { + // Pick up the entire stack from the source slot + click(from); + + // Get the stack we just picked up + ItemStack cursorStack = mc.player.currentScreenHandler.getCursorStack(); + if (cursorStack.isEmpty()) return; + + // Calculate how many items we can actually move (min of what we have and what we want) + int itemsToMove = Math.min(cursorStack.getCount(), count); + + // Use right-click to place items one by one + int originalData = data; + data = 1; // 1 = right-click which places one item at a time + + for (int i = 0; i < itemsToMove; i++) { + click(to); + } + + // Restore original data value + data = originalData; + + // Put back any remaining items to the original slot + if (!mc.player.currentScreenHandler.getCursorStack().isEmpty()) { + click(from); + } + } } } From 4476603235506936d9b853acb62534a6897764e0 Mon Sep 17 00:00:00 2001 From: uxmlen <38371923+uxmlen@users.noreply.github.com> Date: Wed, 7 May 2025 10:34:18 +0300 Subject: [PATCH 2/5] refactor: extract repetitive logic into reusable method 1. Renamed methods `fuelItemFilter` and `smeltableItemFilter` to `isFuelItem` and `isSmeltableItem` for clarity. 2. Extract repetitive logic into reusable method --- .../systems/modules/world/AutoSmelter.java | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index 0cbb9c2022..14461cf090 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -18,6 +18,7 @@ import net.minecraft.screen.AbstractFurnaceScreenHandler; import java.util.List; +import java.util.function.Predicate; public class AutoSmelter extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); @@ -26,7 +27,7 @@ public class AutoSmelter extends Module { .name("fuel-items") .description("Items to use as fuel") .defaultValue(Items.COAL, Items.CHARCOAL) - .filter(this::fuelItemFilter) + .filter(this::isFuelItem) .bypassFilterWhenSavingAndLoading() .build() ); @@ -35,7 +36,7 @@ public class AutoSmelter extends Module { .name("smeltable-items") .description("Items to smelt") .defaultValue(Items.IRON_ORE, Items.GOLD_ORE, Items.COPPER_ORE, Items.RAW_IRON, Items.RAW_COPPER, Items.RAW_GOLD) - .filter(this::smeltableItemFilter) + .filter(this::isSmeltableItem) .bypassFilterWhenSavingAndLoading() .build() ); @@ -60,14 +61,14 @@ public AutoSmelter() { super(Categories.World, "auto-smelter", "Automatically smelts items from your inventory"); } - private boolean fuelItemFilter(Item item) { - if (!Utils.canUpdate()) return false; - - return mc.getNetworkHandler().getFuelRegistry().getFuelItems().contains(item); + private boolean isFuelItem(Item item) { + return Utils.canUpdate() && mc.getNetworkHandler().getFuelRegistry().getFuelItems().contains(item); } - private boolean smeltableItemFilter(Item item) { - return mc.world != null && mc.world.getRecipeManager().getPropertySet(RecipePropertySet.FURNACE_INPUT).canUse(item.getDefaultStack()); + private boolean isSmeltableItem(Item item) { + return mc.world != null && mc.world.getRecipeManager() + .getPropertySet(RecipePropertySet.FURNACE_INPUT) + .canUse(item.getDefaultStack()); } public void tick(AbstractFurnaceScreenHandler c) { @@ -94,18 +95,7 @@ private void insertItems(AbstractFurnaceScreenHandler c) { ItemStack inputItemStack = c.slots.getFirst().getStack(); if (!inputItemStack.isEmpty()) return; - int slot = -1; - - for (int i = 3; i < c.slots.size(); i++) { - ItemStack item = c.slots.get(i).getStack(); - if (!((IAbstractFurnaceScreenHandler) c).meteor$isItemSmeltable(item)) continue; - if (!smeltableItems.get().contains(item.getItem())) continue; - if (!smeltableItemFilter(item.getItem())) continue; - - slot = i; - break; - } - + int slot = findSlot(c, smeltableItems.get(), this::isSmeltableItem); if (disableWhenOutOfItems.get() && slot == -1) { error("You do not have any items in your inventory that can be smelted. Disabling."); toggle(); @@ -130,26 +120,16 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { // Check if we already have the maximum amount of fuel if (!fuelStack.isEmpty() && fuelStack.getCount() >= fuelAmount.get()) return; - // Calculate how much more fuel we need - int neededFuelCount = fuelStack.isEmpty() ? fuelAmount.get() : fuelAmount.get() - fuelStack.getCount(); - // Find fuel in inventory - int slot = -1; - for (int i = 3; i < c.slots.size(); i++) { - ItemStack item = c.slots.get(i).getStack(); - if (!fuelItems.get().contains(item.getItem())) continue; - if (!fuelItemFilter(item.getItem())) continue; - - slot = i; - break; - } - + int slot = findSlot(c, fuelItems.get(), this::isFuelItem); if (disableWhenOutOfItems.get() && slot == -1) { error("You do not have any fuel in your inventory. Disabling."); toggle(); return; } + // Calculate how much more fuel we need + int neededFuelCount = fuelAmount.get() - fuelStack.getCount(); InvUtils.move(neededFuelCount).fromId(slot).toId(1); } @@ -164,10 +144,26 @@ private void takeResults(AbstractFurnaceScreenHandler c) { if (resultStack.isEmpty()) return; InvUtils.shiftClick().slotId(2); - if (!resultStack.isEmpty()) { error("Your inventory is full. Disabling."); toggle(); } } + + /** + * Finds a slot in the player's inventory containing an item from the specified list + * that also satisfies the given filter condition. + * + * @param c The furnace screen handler + * @param items List of items to search for + * @param filter Additional condition the item must satisfy + * @return The slot ID containing a matching item, or -1 if none found + */ + private int findSlot(AbstractFurnaceScreenHandler c, List items, Predicate filter) { + for (int i = 3; i < c.slots.size(); i++) { + ItemStack item = c.slots.get(i).getStack(); + if (items.contains(item.getItem()) && filter.test(item.getItem())) return i; + } + return -1; + } } From 79820826ff7dbb27b5aec8e79e6ecce396cb0383 Mon Sep 17 00:00:00 2001 From: uxmlen <38371923+uxmlen@users.noreply.github.com> Date: Wed, 7 May 2025 10:44:44 +0300 Subject: [PATCH 3/5] fix: remove redundant condition --- .../meteorclient/systems/modules/world/AutoSmelter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index 14461cf090..a820a59721 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -118,7 +118,7 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { if (!fuelStack.isEmpty()) return; // Check if we already have the maximum amount of fuel - if (!fuelStack.isEmpty() && fuelStack.getCount() >= fuelAmount.get()) return; + if (fuelStack.getCount() >= fuelAmount.get()) return; // Find fuel in inventory int slot = findSlot(c, fuelItems.get(), this::isFuelItem); From 9d8602fb4c7437bc8ccc3171cd3527ebbddfb21a Mon Sep 17 00:00:00 2001 From: uxmlen <38371923+uxmlen@users.noreply.github.com> Date: Fri, 16 May 2025 16:45:53 +0300 Subject: [PATCH 4/5] feat: add smart fuel usage setting Added a "smart fuel usage" option to the AutoSmelter module. When enabled, the module calculates the exact amount of fuel needed to smelt the available items, based on the efficiency of the selected fuel type. This prevents wasting fuel and ensures optimal usage. The setting can be toggled in the module's configuration. #5170 --- .../systems/modules/world/AutoSmelter.java | 119 ++++++++++++++++-- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index a820a59721..e910640fac 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -5,7 +5,6 @@ package meteordevelopment.meteorclient.systems.modules.world; -import meteordevelopment.meteorclient.mixininterface.IAbstractFurnaceScreenHandler; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; @@ -23,10 +22,15 @@ public class AutoSmelter extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); + // General + private final Setting> fuelItems = sgGeneral.add(new ItemListSetting.Builder() .name("fuel-items") .description("Items to use as fuel") - .defaultValue(Items.COAL, Items.CHARCOAL) + .defaultValue( + Items.COAL, + Items.CHARCOAL + ) .filter(this::isFuelItem) .bypassFilterWhenSavingAndLoading() .build() @@ -35,7 +39,14 @@ public class AutoSmelter extends Module { private final Setting> smeltableItems = sgGeneral.add(new ItemListSetting.Builder() .name("smeltable-items") .description("Items to smelt") - .defaultValue(Items.IRON_ORE, Items.GOLD_ORE, Items.COPPER_ORE, Items.RAW_IRON, Items.RAW_COPPER, Items.RAW_GOLD) + .defaultValue( + Items.IRON_ORE, + Items.GOLD_ORE, + Items.COPPER_ORE, + Items.RAW_IRON, + Items.RAW_COPPER, + Items.RAW_GOLD + ) .filter(this::isSmeltableItem) .bypassFilterWhenSavingAndLoading() .build() @@ -48,12 +59,20 @@ public class AutoSmelter extends Module { .build() ); + private final Setting smartFuelUsage = sgGeneral.add(new BoolSetting.Builder() + .name("smart-fuel-usage") + .description("Only uses the amount of fuel needed to smelt available items") + .defaultValue(false) + .build() + ); + private final Setting fuelAmount = sgGeneral.add(new IntSetting.Builder() .name("fuel-amount") .description("Amount of fuel to insert in each furnace (1-64).") - .defaultValue(32) + .defaultValue(64) .range(1, 64) .sliderMax(64) + .visible(() -> !smartFuelUsage.get()) .build() ); @@ -61,16 +80,31 @@ public AutoSmelter() { super(Categories.World, "auto-smelter", "Automatically smelts items from your inventory"); } + /** + * Returns true if the item is valid fuel. + */ private boolean isFuelItem(Item item) { return Utils.canUpdate() && mc.getNetworkHandler().getFuelRegistry().getFuelItems().contains(item); } + /** + * Returns true if the item can be smelted. + */ private boolean isSmeltableItem(Item item) { return mc.world != null && mc.world.getRecipeManager() .getPropertySet(RecipePropertySet.FURNACE_INPUT) .canUse(item.getDefaultStack()); } + /** + * Returns how many items can be smelted per fuel item. + */ + private double getFuelEfficiency(Item item) { + int burnTime = mc.getNetworkHandler().getFuelRegistry().getFuelTicks(new ItemStack(item)); + // Each item smelts in 200 ticks + return burnTime > 0 ? burnTime / 200.0 : 0.0; + } + public void tick(AbstractFurnaceScreenHandler c) { // Limit actions to happen every n ticks if (mc.player.age % 10 == 0) return; @@ -114,11 +148,19 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { ItemStack fuelStack = c.slots.get(1).getStack(); // If the furnace is burning, don't do anything - if (c.getFuelProgress() > 0) return; - if (!fuelStack.isEmpty()) return; + if (!fuelStack.isEmpty() || c.getFuelProgress() > 0) return; + + // If smart fuel is enabled, calculate how much fuel we need based on smeltable items + int neededFuelCount = fuelAmount.get(); - // Check if we already have the maximum amount of fuel - if (fuelStack.getCount() >= fuelAmount.get()) return; + if (smartFuelUsage.get()) { + int smeltableItemCount = countSmeltableItems(c); + if (smeltableItemCount == 0) return; + + // Calculate fuel needed based on the burn rate of available fuel + neededFuelCount = calculateRequiredFuel(smeltableItemCount); + if (neededFuelCount == 0) return; + } // Find fuel in inventory int slot = findSlot(c, fuelItems.get(), this::isFuelItem); @@ -128,8 +170,7 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { return; } - // Calculate how much more fuel we need - int neededFuelCount = fuelAmount.get() - fuelStack.getCount(); + // Move the calculated amount of fuel to the furnace InvUtils.move(neededFuelCount).fromId(slot).toId(1); } @@ -154,8 +195,8 @@ private void takeResults(AbstractFurnaceScreenHandler c) { * Finds a slot in the player's inventory containing an item from the specified list * that also satisfies the given filter condition. * - * @param c The furnace screen handler - * @param items List of items to search for + * @param c The furnace screen handler + * @param items List of items to search for * @param filter Additional condition the item must satisfy * @return The slot ID containing a matching item, or -1 if none found */ @@ -166,4 +207,58 @@ private int findSlot(AbstractFurnaceScreenHandler c, List items, Predicate } return -1; } + + /** + * Counts how many smeltable items are available for a single smelting operation + * + * @param c The furnace screen handler + * @return The count of smeltable items for one batch (max 64) + */ + private int countSmeltableItems(AbstractFurnaceScreenHandler c) { + // First check the input slot + ItemStack inputStack = c.slots.get(0).getStack(); + if (!inputStack.isEmpty() && isSmeltableItem(inputStack.getItem())) { + // If there's already something in the input slot, only consider that + return Math.min(inputStack.getCount(), 64); + } + + // Otherwise, find the first stack of smeltable items + for (int i = 3; i < c.slots.size(); i++) { + ItemStack stack = c.slots.get(i).getStack(); + if (!stack.isEmpty() && smeltableItems.get().contains(stack.getItem()) && isSmeltableItem(stack.getItem())) { + return Math.min(stack.getCount(), 64); + } + } + + return 0; + } + + /** + * Calculates how much fuel is needed based on the number of items to smelt + * + * @param itemCount Number of items to smelt + * @return Number of fuel items needed + */ + private int calculateRequiredFuel(int itemCount) { + // If no items to smelt, don't need fuel + if (itemCount <= 0) return 0; + + // Get the first available fuel item + Item fuelItem = fuelItems.get().stream() + .filter(item -> mc.player.currentScreenHandler.slots.stream() + .anyMatch(slot -> slot.getStack().getItem() == item)) + .findFirst() + .orElse(null); + + if (fuelItem == null) return 0; + + // Get efficiency from map with default value of 8 + double itemsPerFuel = Math.max(getFuelEfficiency(fuelItem), 8.0); + + // Calculate how many fuel items are needed + int fuelNeeded = (int) Math.ceil(itemCount / itemsPerFuel); + + // Cap at the max fuel amount setting + return Math.min(fuelNeeded, fuelAmount.get()); + } } From ccbfc1afce6592619bf9f0b85fd3b188ae1e222f Mon Sep 17 00:00:00 2001 From: uxmlen <38371923+uxmlen@users.noreply.github.com> Date: Fri, 16 May 2025 17:21:34 +0300 Subject: [PATCH 5/5] fix: merge partial fuel stacks to fill furnace slot up to fuelAmount --- .../systems/modules/world/AutoSmelter.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java index e910640fac..3d256e5c05 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/world/AutoSmelter.java @@ -147,7 +147,7 @@ private void insertItems(AbstractFurnaceScreenHandler c) { private void checkFuel(AbstractFurnaceScreenHandler c) { ItemStack fuelStack = c.slots.get(1).getStack(); - // If the furnace is burning, don't do anything + // If the furnace is burning or has fuel, don't do anything if (!fuelStack.isEmpty() || c.getFuelProgress() > 0) return; // If smart fuel is enabled, calculate how much fuel we need based on smeltable items @@ -162,16 +162,30 @@ private void checkFuel(AbstractFurnaceScreenHandler c) { if (neededFuelCount == 0) return; } - // Find fuel in inventory - int slot = findSlot(c, fuelItems.get(), this::isFuelItem); - if (disableWhenOutOfItems.get() && slot == -1) { + // Track how much fuel we've added so far + int remainingToAdd = neededFuelCount; + boolean foundAnyFuel = false; + + // Check inventory slots for fuel + for (int i = 3; i < c.slots.size() && remainingToAdd > 0; i++) { + ItemStack stack = c.slots.get(i).getStack(); + + // Skip empty stacks or non-fuel items + if (stack.isEmpty() || !fuelItems.get().contains(stack.getItem()) || !isFuelItem(stack.getItem())) continue; + + // Take as many items as needed (or available) + int amountToTake = Math.min(stack.getCount(), remainingToAdd); + InvUtils.move(amountToTake).fromId(i).toId(1); + + remainingToAdd -= amountToTake; + foundAnyFuel = true; + } + + // If we couldn't find any fuel and the setting is enabled, disable the module + if (!foundAnyFuel && disableWhenOutOfItems.get()) { error("You do not have any fuel in your inventory. Disabling."); toggle(); - return; } - - // Move the calculated amount of fuel to the furnace - InvUtils.move(neededFuelCount).fromId(slot).toId(1); } /**