package me.rigamortis.seppuku.impl.module.misc; import me.rigamortis.seppuku.Seppuku; import me.rigamortis.seppuku.api.event.EventStageable; import me.rigamortis.seppuku.api.event.player.EventUpdateWalkingPlayer; import me.rigamortis.seppuku.api.module.Module; import me.rigamortis.seppuku.api.util.Timer; import me.rigamortis.seppuku.api.value.Value; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.init.Items; import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; /** * Automatically refills the players hotbar. * * @author Old Chum * @since 12/7/19 */ public class HotBarRefillModule extends Module { public final Value<Float> delay = new Value<>("Delay", new String[]{"Del"}, "The amount of delay in milliseconds.", 50.0f); public final Value<Integer> percentage = new Value<>("RefillPercentage", new String[]{"percent", "p", "percent"}, "The percentage a slot should be filled to get refilled.", 50, 0, 100, 1); public final Value<Boolean> offHand = new Value<>("OffHand", new String[]{"oh", "off", "hand"}, "If the off hand should be refilled.", true); private Timer timer = new Timer(); public HotBarRefillModule() { super("HotBarRefill", new String[]{"Replenish", "Refill", "AutoHotBar", "hbr", "Restock", "HBRestock", "HBRefill", "Hotbar"}, "NONE", -1, ModuleType.MISC); } @Listener public void onWalkingUpdate (EventUpdateWalkingPlayer event) { if (this.timer.passed(this.delay.getValue())) { if (event.getStage() == EventStageable.EventStage.PRE) { Minecraft mc = Minecraft.getMinecraft(); if (mc.currentScreen instanceof GuiInventory) { return; } int toRefill = getRefillable(mc.player); if (toRefill != -1) { refillHotbarSlot(mc, toRefill); } } timer.reset(); } } /** * Checks all items in the hotbar that can be refilled * If offhand is on, it is checked first * * @param player The player * @return The index of the first item to be refilled, -1 if there are no refillable items */ private int getRefillable(EntityPlayerSP player) { if (offHand.getValue()) { if (player.getHeldItemOffhand().getItem() != Items.AIR && player.getHeldItemOffhand().getCount() < player.getHeldItemOffhand().getMaxStackSize() && (double) player.getHeldItemOffhand().getCount() / player.getHeldItemOffhand().getMaxStackSize() <= (percentage.getValue() / 100.0)) { return 45; } } for (int i = 0; i < 9; i++) { ItemStack stack = player.inventory.mainInventory.get(i); if (stack.getItem() != Items.AIR && stack.getCount() < stack.getMaxStackSize() && (double) stack.getCount() / stack.getMaxStackSize() <= (percentage.getValue() / 100.0)) { return i; } } return -1; } /** * Searches the player's inventory for the smallest stack. * Gets the smallest stack so that there are not a a bunch * of partially full stacks left in the player's inventory. * * @param player The player * @param itemStack The item type that should be found * @return The index of the smallest stack of the given item, -1 if the given item does not exist */ private int getSmallestStack(EntityPlayerSP player, ItemStack itemStack) { if (itemStack == null) { return -1; } int minCount = itemStack.getMaxStackSize() + 1; int minIndex = -1; // i starts at 9 so that the hotbar is not checked for (int i = 9; i < player.inventory.mainInventory.size(); i++) { ItemStack stack = player.inventory.mainInventory.get(i); if (stack.getItem() != Items.AIR && stack.getItem() == itemStack.getItem() && stack.getCount() < minCount) { minCount = stack.getCount(); minIndex = i; } } return minIndex; } /** * Refills a given slot in the hotbar from an item in the player's inventory. * Uses the slot's current ItemStack to decide what it should be refilled with. * * @param mc The Mincraft instance * @param slot The slot that should be refilled */ public void refillHotbarSlot(Minecraft mc, int slot) { ItemStack stack; if (slot == 45) { // Special case for offhand stack = mc.player.getHeldItemOffhand(); } else { stack = mc.player.inventory.mainInventory.get(slot); } // If the slot is air it cant be refilled if (stack.getItem() == Items.AIR) { return; } // The slot can't be refilled if there is nothing to refill it with int biggestStack = getSmallestStack(mc.player, stack); if (biggestStack == -1) { return; } // Special case for offhand (can't use QUICK_CLICK) if (slot == 45) { mc.playerController.windowClick(mc.player.inventoryContainer.windowId, biggestStack, 0, ClickType.PICKUP, mc.player); mc.playerController.windowClick(mc.player.inventoryContainer.windowId, 45, 0, ClickType.PICKUP, mc.player); mc.playerController.windowClick(mc.player.inventoryContainer.windowId, biggestStack, 0, ClickType.PICKUP, mc.player); return; } int overflow = -1; // The slot a shift click will overflow to for (int i = 0; i < 9 && overflow == -1; i++) { if (mc.player.inventory.mainInventory.get(i).getItem() == Items.AIR) { overflow = i; } } mc.playerController.windowClick(mc.player.inventoryContainer.windowId, biggestStack, 0, ClickType.QUICK_MOVE, mc.player); // If the two stacks don't overflow when combined we don't have to move overflow if (overflow != -1 && mc.player.inventory.mainInventory.get(overflow).getItem() != Items.AIR) { mc.playerController.windowClick(mc.player.inventoryContainer.windowId, biggestStack, overflow, ClickType.SWAP, mc.player); } } }