Подпишитесь на наш Telegram-канал, чтобы всегда быть в курсе важных обновлений! Перейти

Часть функционала Funtime AutoFarm

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
21 Фев 2022
Сообщения
121
Реакции
11
Выберите загрузчик игры
  1. Fabric
Автофарм какао-бобов под фантайм, гораздо еффективнее чем в какой-то дельте. Надо запускать два бота - один ломает, другой сажает, они синкаются и один идет за другим. Бот сам чинит свой топор. Прибыль с одного бота около 30кк в час, строите 10 ферм, запускаете на сутки +пару миллиардов получаете.
Ферму нужно строить чтобы бот ходил под ней, 2 блока под бота + 4 блока бобов. Много параметров фермы hard-coded, поэтому разбирайтесь как сделать чтобы у вас это заработало.
FarmManager.java:
Expand Collapse Copy
package xyz.breadloaf.imguimc.werwedc;

import imgui.type.ImBoolean;
import imgui.type.ImInt;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CocoaBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;

public class FarmManager {
    public static class CocoaFarmer {

        // --- Configuration ---
        public static final ImInt originX = new ImInt(0);
        public static final ImInt originZ = new ImInt(-44);
        public static final ImInt farmMaxX = new ImInt(63);
        public static final ImInt farmMaxZ = new ImInt(0);
        public static final ImBoolean isEnabled = new ImBoolean(false);

        // --- State Machine ---
        private enum State {
            BREAKING,
            CHANGING_LANE_STRAFE,
            BREAKING_RETURN,
            DEPOSITING_FOR_PLANT,  // New state for planter's barrel
            DEPOSITING_FOR_STORAGE, // New state for profit chest
            CHANGING_LANE_ADVANCE,
            RETURNING_TO_ORIGIN,
            REPAIRING,
            WAITING_FOR_GROWTH
        }

        private enum RepairSubState {
            IDLE, LOCATING_BARREL, TAKING_BOTTLES, EQUIPPING_OFFHAND, REPAIRING_WITH_BOTTLES
        }

        private static State currentState = State.REPAIRING;
        private static State stateAfterDeposit;
        private static RepairSubState repairState = RepairSubState.LOCATING_BARREL;

        public static String getCurrentStateName() {
            return currentState.name() + (currentState == State.REPAIRING ? " (" + repairState.name() + ")" : "");
        }

        // --- Farming Logic ---
        private static int currentRowZ = originZ.get();
        private static boolean initialized = false;
        private static boolean wasEnabledLastTick = false;
        private static boolean hasOpenedContainer = false;
        private static int bottlesToTake = 2;
        private static long lastActionTime = 0;
        private static int repairClicksDone = 0;
        private static long lastRepairClickTime = 0;

        public static void reset() {
            isEnabled.set(false);
            currentState = State.BREAKING;
            repairState = RepairSubState.IDLE;
            initialized = false;
            currentRowZ = originZ.get();
        }

        public static void onTick(Minecraft mc) {
            boolean isCurrentlyEnabled = isEnabled.get();

            if (!isCurrentlyEnabled && wasEnabledLastTick) {
                mc.options.keyUp.setDown(false);
                mc.options.keyAttack.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyUse.setDown(false);
                reset();
            }

            wasEnabledLastTick = isCurrentlyEnabled;
            if (!isCurrentlyEnabled) return;

            final LocalPlayer player = mc.player;
            if (player == null) return;

            boolean isGuiOpen = mc.screen != null;
            boolean shouldPause = isGuiOpen && currentState != State.DEPOSITING_FOR_PLANT && currentState != State.DEPOSITING_FOR_STORAGE && currentState != State.REPAIRING;
            if (shouldPause) {
                mc.options.keyUp.setDown(false);
                mc.options.keyAttack.setDown(false);
                mc.options.keyRight.setDown(false);
                return;
            }

            if (!initialized) {
                currentRowZ = originZ.get();
                initialized = true;
            }

            switch (currentState) {
                case BREAKING:
                    if (player.getX() >= farmMaxX.get()) {
                        mc.options.keyUp.setDown(false);
                        currentState = State.CHANGING_LANE_STRAFE;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);

                    if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                        mc.gameMode.startDestroyBlock(blockHitResult.getBlockPos(), blockHitResult.getDirection());
                    }
                    break;

                case CHANGING_LANE_STRAFE:
                    final double targetStrafeZ = currentRowZ + 1 - 0.3;
                    if (player.getZ() >= targetStrafeZ - 0.001) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.BREAKING_RETURN;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case BREAKING_RETURN:
                    if (player.getZ() >= farmMaxZ.get() - 1) {
                        if (player.getX() <= originX.get() + 1.3 + 0.001) {
                            mc.options.keyUp.setDown(false);
                            stateAfterDeposit = State.RETURNING_TO_ORIGIN;
                            currentState = State.DEPOSITING_FOR_PLANT; // Start deposit sequence
                            return;
                        }
                    } else {
                        if (player.getX() <= originX.get() + 0.3 + 0.001) {
                            mc.options.keyUp.setDown(false);
                            currentRowZ += 3;
                            stateAfterDeposit = State.CHANGING_LANE_ADVANCE;
                            currentState = State.DEPOSITING_FOR_PLANT; // Start deposit sequence
                            return;
                        }
                    }
                    if (player.getYRot() != 90f) player.setYRot(90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);

                    if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                        mc.gameMode.startDestroyBlock(blockHitResult.getBlockPos(), blockHitResult.getDirection());
                    }
                    break;

                case DEPOSITING_FOR_PLANT:
                    handleDepositingForPlant(mc, player);
                    break;

                case DEPOSITING_FOR_STORAGE:
                    handleDepositingForStorage(mc, player);
                    break;

                case CHANGING_LANE_ADVANCE:
                    final double targetAdvanceZ = currentRowZ - 0.488;
                    if (player.getZ() >= targetAdvanceZ - 0.01) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.BREAKING;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case RETURNING_TO_ORIGIN:
                    if (mc.screen instanceof AbstractContainerScreen) {
                        player.closeContainer();
                    }
                    final double targetReturnZ = originZ.get() - 0.7;
                    if (player.getZ() <= targetReturnZ + 0.01) {
                        mc.options.keyUp.setDown(false);
                        repairState = RepairSubState.LOCATING_BARREL;
                        currentState = State.REPAIRING;
                        repairClicksDone = 0; // Reset for the new repair cycle
                        currentRowZ = originZ.get();
                        return;
                    }
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (player.getXRot() != 0f) player.setXRot(0f);
                    if (currentRowZ != originZ.get()) currentRowZ = originZ.get();
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);
                    break;

                case REPAIRING:
                    handleRepairing(mc, player);
                    break;

                case WAITING_FOR_GROWTH:
                    int grownCocoaCount = 0;
                    for (int x = -3; x <= 3; x++) {
                        for (int y = -3; y <= 3; y++) {
                            for (int z = -3; z <= 3; z++) {
                                BlockPos pos = player.blockPosition().offset(x, y, z);
                                BlockState state = mc.level.getBlockState(pos);
                                if (state.getBlock() instanceof CocoaBlock && state.getValue(CocoaBlock.AGE) == 2) {
                                    grownCocoaCount++;
                                }
                            }
                        }
                    }
                    if (grownCocoaCount >= 3) {
                        currentState = State.BREAKING;
                    }
                    break;
            }
        }

        private static void handleDepositingForPlant(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedContainer = true;
                if (System.currentTimeMillis() - lastActionTime < 200) return;

                int cocoaInBarrel = countItemsInContainer(player, Items.COCOA_BEANS);
                int cocoaInPlayer = countItemsInInventory(player, Items.COCOA_BEANS);

                if (cocoaInBarrel >= 8 * 64 || cocoaInPlayer == 0) {
                    player.closeContainer();
                    return;
                }

                // Find a stack in player inv to move
                int playerSlot = -1;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        playerSlot = getContainerSlotFromInventory(player, i);
                        break;
                    }
                }

                if (playerSlot != -1) {
                    mc.gameMode.handleInventoryMouseClick(player.containerMenu.containerId, playerSlot, 0, ClickType.QUICK_MOVE, player);
                    lastActionTime = System.currentTimeMillis();
                } else { // No more cocoa to move
                    player.closeContainer();
                }

            } else { // GUI is not open
                if (hasOpenedContainer) {
                    hasOpenedContainer = false;
                    currentState = State.DEPOSITING_FOR_STORAGE; // Proceed to next deposit stage
                    return;
                }
                if (player.getYRot() != 90f) player.setYRot(90f);
                if (player.getXRot() != 90f) player.setXRot(90f); // Look down for barrel
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.BARREL)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleDepositingForStorage(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedContainer = true;
                boolean hasCocoa = false;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        hasCocoa = true;
                        int slotId = getContainerSlotFromInventory(player, i);
                        if(slotId != -1) {
                            mc.gameMode.handleInventoryMouseClick(player.containerMenu.containerId, slotId, 0, ClickType.QUICK_MOVE, player);
                            return;
                        }
                    }
                }
                if (!hasCocoa) player.closeContainer();
            } else {
                if (hasOpenedContainer) {
                    hasOpenedContainer = false;
                    currentState = stateAfterDeposit; // Transition to final destination
                    return;
                }
                if (player.getYRot() != 90f) player.setYRot(90f);
                if (player.getXRot() != 0f) player.setXRot(0f); // Look straight for chest
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.CHEST)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleRepairing(Minecraft mc, LocalPlayer player) {
            // Check if we have completed all 60 clicks
            if (repairClicksDone >= 130) {
                currentState = State.WAITING_FOR_GROWTH;
                return;
            }

            // Set the player's rotation
            if (player.getYRot() != -170f) player.setYRot(-170f);
            if (player.getXRot() != 0f) player.setXRot(0f);

            // Check if 500ms have passed since the last click
            if (System.currentTimeMillis() - lastRepairClickTime > 500) {
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.LEVER)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                        repairClicksDone++;
                        lastRepairClickTime = System.currentTimeMillis();
                    }
                }
            }
        }

        private static int getContainerSlotFromInventory(LocalPlayer player, int inventorySlot) {
            for (int i = 0; i < player.containerMenu.slots.size(); i++) {
                var slot = player.containerMenu.slots.get(i);
                if (slot.container == player.getInventory() && slot.getContainerSlot() == inventorySlot) {
                    return i;
                }
            }
            return -1;
        }

        private static int countItemsInContainer(LocalPlayer player, net.minecraft.world.item.Item item) {
            if (!(Minecraft.getInstance().screen instanceof AbstractContainerScreen)) return 0;
            int count = 0;
            int containerSlots = player.containerMenu.slots.size() - player.getInventory().getContainerSize();
            for(int i = 0; i < containerSlots; i++) {
                ItemStack stack = player.containerMenu.slots.get(i).getItem();
                if(stack.is(item)) {
                    count += stack.getCount();
                }
            }
            return count;
        }

        private static int countItemsInInventory(LocalPlayer player, net.minecraft.world.item.Item item) {
            int count = 0;
            for(ItemStack stack : player.getInventory().items) {
                if(stack.is(item)) {
                    count += stack.getCount();
                }
            }
            return count;
        }
    }
}

PlantManager.java:
Expand Collapse Copy
package xyz.breadloaf.imguimc.werwedc;

import imgui.type.ImBoolean;
import imgui.type.ImInt;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.ChatScreen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CocoaBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;

public class PlantManager {
    public static class CocoaPlanter {

        // --- Configuration ---
        public static final ImInt originX = new ImInt(0);
        public static final ImInt originZ = new ImInt(-44);
        public static final ImInt farmMaxX = new ImInt(63);
        public static final ImInt farmMaxZ = new ImInt(0);
        public static final ImBoolean isEnabled = new ImBoolean(false);

        // --- State Machine ---
        private enum State {
            WAITING_FOR_HARVEST,
            DEPOSITING_LEFTOVERS, // New state
            TAKING_COCOA,
            PLANTING,
            CHANGING_LANE_STRAFE,
            PLANTING_RETURN,
            CHANGING_LANE_ADVANCE,
            RETURNING_TO_ORIGIN
        }

        private static State currentState = State.TAKING_COCOA;
        private static boolean wasEnabledLastTick = false;
        private static int plantStage = 0;
        private static boolean hasOpenedChestForTaking = false;
        private static boolean hasOpenedChestForDepositing = false;
        private static long lastPlantTime = 0;
        private static long lastInventoryActionTime = 0;
        private static int lastFinishedBlockX = -10000;
        private static int currentRowZ = originZ.get();
        private static boolean initialized = false;
        private static boolean justReturnedToOrigin = false;
        private static long lastStartedReturningToOriginTime = 0;
        public static String getCurrentStateName() {
            return currentState.name();
        }

        public static void reset() {
            isEnabled.set(false);
            currentState = State.TAKING_COCOA;
            plantStage = 0;
            lastFinishedBlockX = -10000;
            initialized = false;
            hasOpenedChestForTaking = false;
            hasOpenedChestForDepositing = false;
            justReturnedToOrigin = false;
            currentRowZ = originZ.get();
        }

        public static void onTick(Minecraft mc) {
            boolean isCurrentlyEnabled = isEnabled.get();

            if (!isCurrentlyEnabled && wasEnabledLastTick) {
                mc.options.keyUp.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyLeft.setDown(false);
                reset();
            }

            wasEnabledLastTick = isCurrentlyEnabled;

            if (!isCurrentlyEnabled) {
                return;
            }

            final LocalPlayer player = mc.player;
            if (player == null) {
                return;
            }

            if (mc.screen instanceof ChatScreen) {
                mc.options.keyUp.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyLeft.setDown(false);
                return;
            }

            if (!initialized) {
                currentRowZ = originZ.get();
                initialized = true;
            }

            switch (currentState) {
                case WAITING_FOR_HARVEST:
                    for (int x = -3; x <= 3; x++) {
                        for (int y = -3; y <= 3; y++) {
                            for (int z = -3; z <= 3; z++) {
                                BlockPos pos = player.blockPosition().offset(x, y, z);
                                if (mc.level.getBlockState(pos).getBlock() instanceof CocoaBlock) {
                                    return;
                                }
                            }
                        }
                    }
                    currentState = State.DEPOSITING_LEFTOVERS;
                    break;

                case DEPOSITING_LEFTOVERS:
                    handleDepositingLeftovers(mc, player);
                    break;

                case TAKING_COCOA:
                    handleTakingCocoa(mc, player);
                    break;

                case PLANTING:
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);

                    if (player.getBlockX() >= farmMaxX.get()) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.CHANGING_LANE_STRAFE;
                        break;
                    }

                    if (!ensureHoldingCocoa(player) || player.getBlockX() == lastFinishedBlockX) {
                        break;
                    }

                    if (System.currentTimeMillis() - lastPlantTime > 25) {
                        performPlanting(mc, player, false);
                        if (plantStage >= 4) {
                            plantStage = 0;
                            lastFinishedBlockX = player.getBlockX();
                        }
                    }
                    break;

                case PLANTING_RETURN:
                    if (player.getYRot() != 0f) player.setYRot(0f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);

                    if (player.getZ() >= farmMaxZ.get() - 1) {
                        if (player.getX() <= originX.get() + 1.3 + 0.001) {
                            mc.options.keyRight.setDown(false);
                            currentState = State.RETURNING_TO_ORIGIN;
                            lastStartedReturningToOriginTime = System.currentTimeMillis();
                            break;
                        }
                    } else {
                        if (player.getX() <= originX.get() + 0.3 + 0.001) {
                            mc.options.keyRight.setDown(false);
                            currentRowZ += 3;
                            currentState = State.CHANGING_LANE_ADVANCE;
                            break;
                        }
                    }

                    if (!ensureHoldingCocoa(player) || player.getBlockX() == lastFinishedBlockX) {
                        break;
                    }

                    if (System.currentTimeMillis() - lastPlantTime > 25) {
                        performPlanting(mc, player, true);
                        if (plantStage >= 4) {
                            plantStage = 0;
                            lastFinishedBlockX = player.getBlockX();
                        }
                    }
                    break;

                case CHANGING_LANE_STRAFE:
                    final double targetStrafeZ = currentRowZ + 1 - 0.3;
                    if (player.getZ() >= targetStrafeZ - 0.001) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.PLANTING_RETURN;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case CHANGING_LANE_ADVANCE:
                    final double targetAdvanceZ = currentRowZ - 0.488;
                    if(player.getZ() >= targetAdvanceZ - 0.01) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.DEPOSITING_LEFTOVERS;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case RETURNING_TO_ORIGIN:
                    if (System.currentTimeMillis() - lastStartedReturningToOriginTime < 30000){
                        break;
                    }
                    final double targetReturnZ = originZ.get() - 0.7;
                    if (player.getZ() <= targetReturnZ + 0.01) {
                        mc.options.keyUp.setDown(false);
                        justReturnedToOrigin = true;
                        currentState = State.WAITING_FOR_HARVEST;
                        if (currentRowZ != originZ.get()) currentRowZ = originZ.get();
                        return;
                    }
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);
                    break;
            }
        }

        // --- Helper Methods ---

        private static void handleDepositingLeftovers(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedChestForDepositing = true;
                boolean hasCocoa = false;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        hasCocoa = true;
                        int slotId = getContainerSlotFromInventory(player, i);
                        if(slotId != -1) {
                            clickSlot(mc, slotId, ClickType.QUICK_MOVE);
                            return; // Do one move per tick
                        }
                    }
                }
                if (!hasCocoa) player.closeContainer();
            } else {
                if (hasOpenedChestForDepositing) {
                    hasOpenedChestForDepositing = false;
                    currentState = State.TAKING_COCOA;
                    return;
                }
                if (player.getYRot() != 45f) player.setYRot(45f);
                if (player.getXRot() != 0f) player.setXRot(0f);
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.CHEST)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleTakingCocoa(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedChestForTaking = true;
                if (System.currentTimeMillis() - lastInventoryActionTime < 150) return;

                if (!player.containerMenu.getCarried().isEmpty()) {
                    int targetHotbarSlot = findAvailableHotbarSlot(player);
                    if (targetHotbarSlot != -1) {
                        int containerSlot = getContainerSlotFromInventory(player, targetHotbarSlot);
                        clickSlot(mc, containerSlot);
                    } else {
                        player.closeContainer();
                    }
                    return;
                }

                int slotToClear = findSlotToClearInHotbar(player);
                if (slotToClear != -1) {
                    int containerSlot = getContainerSlotFromInventory(player, slotToClear);
                    clickSlot(mc, containerSlot, ClickType.QUICK_MOVE);
                    return;
                }

                if (countFullCocoaStacksInHotbar(player) < 8) {
                    int sourceChestSlot = findFullCocoaStackInChest(player);
                    if (sourceChestSlot != -1) {
                        clickSlot(mc, sourceChestSlot, ClickType.QUICK_MOVE);
                        return;
                    }
                }
                player.closeContainer();
            } else {
                if (hasOpenedChestForTaking) {
                    if (System.currentTimeMillis() - lastInventoryActionTime < 250) return;
                    hasOpenedChestForTaking = false;

                    if (player.getInventory().contains(new ItemStack(Items.COCOA_BEANS))) {
                        if (justReturnedToOrigin) justReturnedToOrigin = false;
                        currentState = State.PLANTING;
                    } else {
                        reset();
                    }
                    return;
                }

                float targetYaw;
                float targetPitch;

                // Case 1: Is this the last row?
                if (currentRowZ + 3 >= farmMaxZ.get()) {
                    targetYaw = -68.6f;
                    targetPitch = 44.5f;
                }
                // Case 2: Is this the first row of a new cycle? (or the very first start)
                else if (justReturnedToOrigin || !initialized) {
                    targetYaw = 21.2f;
                    targetPitch = 47.9f;
                }
                // Case 3: All other intermediate rows
                else {
                    targetYaw = 0f;
                    targetPitch = 50f;
                }

                if (player.getYRot() != targetYaw) player.setYRot(targetYaw);
                if (player.getXRot() != targetPitch) player.setXRot(targetPitch);
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.BARREL)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void clickSlot(Minecraft mc, int slotId) {
            clickSlot(mc, slotId, ClickType.PICKUP);
        }

        private static void clickSlot(Minecraft mc, int slotId, ClickType type) {
            mc.gameMode.handleInventoryMouseClick(mc.player.containerMenu.containerId, slotId, 0, type, mc.player);
            lastInventoryActionTime = System.currentTimeMillis();
        }

        private static boolean ensureHoldingCocoa(LocalPlayer player) {
            if (player.getMainHandItem().is(Items.COCOA_BEANS)) return true;
            for (int i = 0; i < 9; i++) {
                if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                    player.getInventory().selected = i;
                    return true;
                }
            }
            return false;
        }

        private static int findAvailableHotbarSlot(LocalPlayer player) {
            for (int i = 0; i < 8; i++) {
                if (player.getInventory().getItem(i).isEmpty()) return i;
            }
            return -1;
        }

        private static int findSlotToClearInHotbar(LocalPlayer player) {
            for (int i = 0; i < 8; i++) {
                ItemStack stack = player.getInventory().getItem(i);
                if (!stack.isEmpty() && (!stack.is(Items.COCOA_BEANS) || stack.getCount() < 64)) {
                    return i;
                }
            }
            return -1;
        }

        private static int countFullCocoaStacksInHotbar(LocalPlayer player) {
            int count = 0;
            for(int i = 0; i < 8; i++) {
                ItemStack stack = player.getInventory().getItem(i);
                if (stack.is(Items.COCOA_BEANS) && stack.getCount() == 64) {
                    count++;
                }
            }
            return count;
        }

        private static int findFullCocoaStackInChest(LocalPlayer player) {
            int chestSlotCount = player.containerMenu.slots.size() - player.getInventory().getContainerSize();
            for (int i = 0; i < chestSlotCount; i++) {
                ItemStack stack = player.containerMenu.slots.get(i).getItem();
                if (stack.is(Items.COCOA_BEANS) && stack.getCount() == 64) {
                    return i;
                }
            }
            return -1;
        }

        private static int getContainerSlotFromInventory(LocalPlayer player, int inventorySlot) {
            for (int i = 0; i < player.containerMenu.slots.size(); i++) {
                var slot = player.containerMenu.slots.get(i);
                if (slot.container == player.getInventory() && slot.getContainerSlot() == inventorySlot) {
                    return i;
                }
            }
            return -1;
        }

        private static void performPlanting(Minecraft mc, LocalPlayer player, boolean isReturn) {
            BlockPos logPos;
            float pitch;
            Direction hitDirection;
            Vec3 hitVec;

            if (isReturn) {
                switch(plantStage) {
                    case 0: logPos = player.blockPosition().south().above(5); pitch = -85.3f; break;
                    case 1: logPos = player.blockPosition().south().above(4); pitch = -83f;   break;
                    case 2: logPos = player.blockPosition().south().above(3); pitch = -80f;   break;
                    case 3: logPos = player.blockPosition().south().above(2); pitch = -60f;   break;
                    default: return;
                }
                hitDirection = Direction.NORTH;
                hitVec = new Vec3(logPos.getX() + 0.5, logPos.getY() + 0.5, logPos.getZ());
            } else {
                switch(plantStage) {
                    case 0: logPos = player.blockPosition().north().above(5); pitch = -82f; break;
                    case 1: logPos = player.blockPosition().north().above(4); pitch = -80f;   break;
                    case 2: logPos = player.blockPosition().north().above(3); pitch = -73f;   break;
                    case 3: logPos = player.blockPosition().north().above(2); pitch = -60f;   break;
                    default: return;
                }
                hitDirection = Direction.SOUTH;
                hitVec = new Vec3(logPos.getX() + 0.5, logPos.getY() + 0.5, logPos.getZ() + 1.0);
            }

            player.setXRot(pitch);

            if (mc.level.getBlockState(logPos).is(BlockTags.JUNGLE_LOGS)) {
                BlockHitResult hitResult = new BlockHitResult(hitVec, hitDirection, logPos, false);
                mc.gameMode.useItemOn(player, InteractionHand.MAIN_HAND, hitResult);
            }

            plantStage++;
            lastPlantTime = System.currentTimeMillis();
        }
    }
}
Какой должна быть ферма:

1758693428991.png
 
Последнее редактирование:
Автофарм какао-бобов под фантайм, гораздо еффективнее чем в какой-то дельте. Надо запускать два бота - один ломает, другой сажает, они синкаются и один идет за другим. Бот сам чинит свой топор. Прибыль с одного бота около 30кк в час, строите 10 ферм, запускаете на сутки +пару миллиардов получаете.
Ферму нужно строить чтобы бот ходил под ней, 2 блока под бота + 4 блока бобов. Много параметров фермы hard-coded, поэтому разбирайтесь как сделать чтобы у вас это заработало.
FarmManager.java:
Expand Collapse Copy
package xyz.breadloaf.imguimc.werwedc;

import imgui.type.ImBoolean;
import imgui.type.ImInt;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CocoaBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;

public class FarmManager {
    public static class CocoaFarmer {

        // --- Configuration ---
        public static final ImInt originX = new ImInt(0);
        public static final ImInt originZ = new ImInt(-44);
        public static final ImInt farmMaxX = new ImInt(63);
        public static final ImInt farmMaxZ = new ImInt(0);
        public static final ImBoolean isEnabled = new ImBoolean(false);

        // --- State Machine ---
        private enum State {
            BREAKING,
            CHANGING_LANE_STRAFE,
            BREAKING_RETURN,
            DEPOSITING_FOR_PLANT,  // New state for planter's barrel
            DEPOSITING_FOR_STORAGE, // New state for profit chest
            CHANGING_LANE_ADVANCE,
            RETURNING_TO_ORIGIN,
            REPAIRING,
            WAITING_FOR_GROWTH
        }

        private enum RepairSubState {
            IDLE, LOCATING_BARREL, TAKING_BOTTLES, EQUIPPING_OFFHAND, REPAIRING_WITH_BOTTLES
        }

        private static State currentState = State.REPAIRING;
        private static State stateAfterDeposit;
        private static RepairSubState repairState = RepairSubState.LOCATING_BARREL;

        public static String getCurrentStateName() {
            return currentState.name() + (currentState == State.REPAIRING ? " (" + repairState.name() + ")" : "");
        }

        // --- Farming Logic ---
        private static int currentRowZ = originZ.get();
        private static boolean initialized = false;
        private static boolean wasEnabledLastTick = false;
        private static boolean hasOpenedContainer = false;
        private static int bottlesToTake = 2;
        private static long lastActionTime = 0;
        private static int repairClicksDone = 0;
        private static long lastRepairClickTime = 0;

        public static void reset() {
            isEnabled.set(false);
            currentState = State.BREAKING;
            repairState = RepairSubState.IDLE;
            initialized = false;
            currentRowZ = originZ.get();
        }

        public static void onTick(Minecraft mc) {
            boolean isCurrentlyEnabled = isEnabled.get();

            if (!isCurrentlyEnabled && wasEnabledLastTick) {
                mc.options.keyUp.setDown(false);
                mc.options.keyAttack.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyUse.setDown(false);
                reset();
            }

            wasEnabledLastTick = isCurrentlyEnabled;
            if (!isCurrentlyEnabled) return;

            final LocalPlayer player = mc.player;
            if (player == null) return;

            boolean isGuiOpen = mc.screen != null;
            boolean shouldPause = isGuiOpen && currentState != State.DEPOSITING_FOR_PLANT && currentState != State.DEPOSITING_FOR_STORAGE && currentState != State.REPAIRING;
            if (shouldPause) {
                mc.options.keyUp.setDown(false);
                mc.options.keyAttack.setDown(false);
                mc.options.keyRight.setDown(false);
                return;
            }

            if (!initialized) {
                currentRowZ = originZ.get();
                initialized = true;
            }

            switch (currentState) {
                case BREAKING:
                    if (player.getX() >= farmMaxX.get()) {
                        mc.options.keyUp.setDown(false);
                        currentState = State.CHANGING_LANE_STRAFE;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);

                    if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                        mc.gameMode.startDestroyBlock(blockHitResult.getBlockPos(), blockHitResult.getDirection());
                    }
                    break;

                case CHANGING_LANE_STRAFE:
                    final double targetStrafeZ = currentRowZ + 1 - 0.3;
                    if (player.getZ() >= targetStrafeZ - 0.001) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.BREAKING_RETURN;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case BREAKING_RETURN:
                    if (player.getZ() >= farmMaxZ.get() - 1) {
                        if (player.getX() <= originX.get() + 1.3 + 0.001) {
                            mc.options.keyUp.setDown(false);
                            stateAfterDeposit = State.RETURNING_TO_ORIGIN;
                            currentState = State.DEPOSITING_FOR_PLANT; // Start deposit sequence
                            return;
                        }
                    } else {
                        if (player.getX() <= originX.get() + 0.3 + 0.001) {
                            mc.options.keyUp.setDown(false);
                            currentRowZ += 3;
                            stateAfterDeposit = State.CHANGING_LANE_ADVANCE;
                            currentState = State.DEPOSITING_FOR_PLANT; // Start deposit sequence
                            return;
                        }
                    }
                    if (player.getYRot() != 90f) player.setYRot(90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);

                    if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                        mc.gameMode.startDestroyBlock(blockHitResult.getBlockPos(), blockHitResult.getDirection());
                    }
                    break;

                case DEPOSITING_FOR_PLANT:
                    handleDepositingForPlant(mc, player);
                    break;

                case DEPOSITING_FOR_STORAGE:
                    handleDepositingForStorage(mc, player);
                    break;

                case CHANGING_LANE_ADVANCE:
                    final double targetAdvanceZ = currentRowZ - 0.488;
                    if (player.getZ() >= targetAdvanceZ - 0.01) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.BREAKING;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (player.getXRot() != -60f) player.setXRot(-60f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case RETURNING_TO_ORIGIN:
                    if (mc.screen instanceof AbstractContainerScreen) {
                        player.closeContainer();
                    }
                    final double targetReturnZ = originZ.get() - 0.7;
                    if (player.getZ() <= targetReturnZ + 0.01) {
                        mc.options.keyUp.setDown(false);
                        repairState = RepairSubState.LOCATING_BARREL;
                        currentState = State.REPAIRING;
                        repairClicksDone = 0; // Reset for the new repair cycle
                        currentRowZ = originZ.get();
                        return;
                    }
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (player.getXRot() != 0f) player.setXRot(0f);
                    if (currentRowZ != originZ.get()) currentRowZ = originZ.get();
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);
                    break;

                case REPAIRING:
                    handleRepairing(mc, player);
                    break;

                case WAITING_FOR_GROWTH:
                    int grownCocoaCount = 0;
                    for (int x = -3; x <= 3; x++) {
                        for (int y = -3; y <= 3; y++) {
                            for (int z = -3; z <= 3; z++) {
                                BlockPos pos = player.blockPosition().offset(x, y, z);
                                BlockState state = mc.level.getBlockState(pos);
                                if (state.getBlock() instanceof CocoaBlock && state.getValue(CocoaBlock.AGE) == 2) {
                                    grownCocoaCount++;
                                }
                            }
                        }
                    }
                    if (grownCocoaCount >= 3) {
                        currentState = State.BREAKING;
                    }
                    break;
            }
        }

        private static void handleDepositingForPlant(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedContainer = true;
                if (System.currentTimeMillis() - lastActionTime < 200) return;

                int cocoaInBarrel = countItemsInContainer(player, Items.COCOA_BEANS);
                int cocoaInPlayer = countItemsInInventory(player, Items.COCOA_BEANS);

                if (cocoaInBarrel >= 8 * 64 || cocoaInPlayer == 0) {
                    player.closeContainer();
                    return;
                }

                // Find a stack in player inv to move
                int playerSlot = -1;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        playerSlot = getContainerSlotFromInventory(player, i);
                        break;
                    }
                }

                if (playerSlot != -1) {
                    mc.gameMode.handleInventoryMouseClick(player.containerMenu.containerId, playerSlot, 0, ClickType.QUICK_MOVE, player);
                    lastActionTime = System.currentTimeMillis();
                } else { // No more cocoa to move
                    player.closeContainer();
                }

            } else { // GUI is not open
                if (hasOpenedContainer) {
                    hasOpenedContainer = false;
                    currentState = State.DEPOSITING_FOR_STORAGE; // Proceed to next deposit stage
                    return;
                }
                if (player.getYRot() != 90f) player.setYRot(90f);
                if (player.getXRot() != 90f) player.setXRot(90f); // Look down for barrel
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.BARREL)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleDepositingForStorage(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedContainer = true;
                boolean hasCocoa = false;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        hasCocoa = true;
                        int slotId = getContainerSlotFromInventory(player, i);
                        if(slotId != -1) {
                            mc.gameMode.handleInventoryMouseClick(player.containerMenu.containerId, slotId, 0, ClickType.QUICK_MOVE, player);
                            return;
                        }
                    }
                }
                if (!hasCocoa) player.closeContainer();
            } else {
                if (hasOpenedContainer) {
                    hasOpenedContainer = false;
                    currentState = stateAfterDeposit; // Transition to final destination
                    return;
                }
                if (player.getYRot() != 90f) player.setYRot(90f);
                if (player.getXRot() != 0f) player.setXRot(0f); // Look straight for chest
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.CHEST)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleRepairing(Minecraft mc, LocalPlayer player) {
            // Check if we have completed all 60 clicks
            if (repairClicksDone >= 130) {
                currentState = State.WAITING_FOR_GROWTH;
                return;
            }

            // Set the player's rotation
            if (player.getYRot() != -170f) player.setYRot(-170f);
            if (player.getXRot() != 0f) player.setXRot(0f);

            // Check if 500ms have passed since the last click
            if (System.currentTimeMillis() - lastRepairClickTime > 500) {
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.LEVER)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                        repairClicksDone++;
                        lastRepairClickTime = System.currentTimeMillis();
                    }
                }
            }
        }

        private static int getContainerSlotFromInventory(LocalPlayer player, int inventorySlot) {
            for (int i = 0; i < player.containerMenu.slots.size(); i++) {
                var slot = player.containerMenu.slots.get(i);
                if (slot.container == player.getInventory() && slot.getContainerSlot() == inventorySlot) {
                    return i;
                }
            }
            return -1;
        }

        private static int countItemsInContainer(LocalPlayer player, net.minecraft.world.item.Item item) {
            if (!(Minecraft.getInstance().screen instanceof AbstractContainerScreen)) return 0;
            int count = 0;
            int containerSlots = player.containerMenu.slots.size() - player.getInventory().getContainerSize();
            for(int i = 0; i < containerSlots; i++) {
                ItemStack stack = player.containerMenu.slots.get(i).getItem();
                if(stack.is(item)) {
                    count += stack.getCount();
                }
            }
            return count;
        }

        private static int countItemsInInventory(LocalPlayer player, net.minecraft.world.item.Item item) {
            int count = 0;
            for(ItemStack stack : player.getInventory().items) {
                if(stack.is(item)) {
                    count += stack.getCount();
                }
            }
            return count;
        }
    }
}

PlantManager.java:
Expand Collapse Copy
package xyz.breadloaf.imguimc.werwedc;

import imgui.type.ImBoolean;
import imgui.type.ImInt;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.ChatScreen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CocoaBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;

public class PlantManager {
    public static class CocoaPlanter {

        // --- Configuration ---
        public static final ImInt originX = new ImInt(0);
        public static final ImInt originZ = new ImInt(-44);
        public static final ImInt farmMaxX = new ImInt(63);
        public static final ImInt farmMaxZ = new ImInt(0);
        public static final ImBoolean isEnabled = new ImBoolean(false);

        // --- State Machine ---
        private enum State {
            WAITING_FOR_HARVEST,
            DEPOSITING_LEFTOVERS, // New state
            TAKING_COCOA,
            PLANTING,
            CHANGING_LANE_STRAFE,
            PLANTING_RETURN,
            CHANGING_LANE_ADVANCE,
            RETURNING_TO_ORIGIN
        }

        private static State currentState = State.TAKING_COCOA;
        private static boolean wasEnabledLastTick = false;
        private static int plantStage = 0;
        private static boolean hasOpenedChestForTaking = false;
        private static boolean hasOpenedChestForDepositing = false;
        private static long lastPlantTime = 0;
        private static long lastInventoryActionTime = 0;
        private static int lastFinishedBlockX = -10000;
        private static int currentRowZ = originZ.get();
        private static boolean initialized = false;
        private static boolean justReturnedToOrigin = false;
        private static long lastStartedReturningToOriginTime = 0;
        public static String getCurrentStateName() {
            return currentState.name();
        }

        public static void reset() {
            isEnabled.set(false);
            currentState = State.TAKING_COCOA;
            plantStage = 0;
            lastFinishedBlockX = -10000;
            initialized = false;
            hasOpenedChestForTaking = false;
            hasOpenedChestForDepositing = false;
            justReturnedToOrigin = false;
            currentRowZ = originZ.get();
        }

        public static void onTick(Minecraft mc) {
            boolean isCurrentlyEnabled = isEnabled.get();

            if (!isCurrentlyEnabled && wasEnabledLastTick) {
                mc.options.keyUp.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyLeft.setDown(false);
                reset();
            }

            wasEnabledLastTick = isCurrentlyEnabled;

            if (!isCurrentlyEnabled) {
                return;
            }

            final LocalPlayer player = mc.player;
            if (player == null) {
                return;
            }

            if (mc.screen instanceof ChatScreen) {
                mc.options.keyUp.setDown(false);
                mc.options.keyRight.setDown(false);
                mc.options.keyLeft.setDown(false);
                return;
            }

            if (!initialized) {
                currentRowZ = originZ.get();
                initialized = true;
            }

            switch (currentState) {
                case WAITING_FOR_HARVEST:
                    for (int x = -3; x <= 3; x++) {
                        for (int y = -3; y <= 3; y++) {
                            for (int z = -3; z <= 3; z++) {
                                BlockPos pos = player.blockPosition().offset(x, y, z);
                                if (mc.level.getBlockState(pos).getBlock() instanceof CocoaBlock) {
                                    return;
                                }
                            }
                        }
                    }
                    currentState = State.DEPOSITING_LEFTOVERS;
                    break;

                case DEPOSITING_LEFTOVERS:
                    handleDepositingLeftovers(mc, player);
                    break;

                case TAKING_COCOA:
                    handleTakingCocoa(mc, player);
                    break;

                case PLANTING:
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);

                    if (player.getBlockX() >= farmMaxX.get()) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.CHANGING_LANE_STRAFE;
                        break;
                    }

                    if (!ensureHoldingCocoa(player) || player.getBlockX() == lastFinishedBlockX) {
                        break;
                    }

                    if (System.currentTimeMillis() - lastPlantTime > 25) {
                        performPlanting(mc, player, false);
                        if (plantStage >= 4) {
                            plantStage = 0;
                            lastFinishedBlockX = player.getBlockX();
                        }
                    }
                    break;

                case PLANTING_RETURN:
                    if (player.getYRot() != 0f) player.setYRot(0f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);

                    if (player.getZ() >= farmMaxZ.get() - 1) {
                        if (player.getX() <= originX.get() + 1.3 + 0.001) {
                            mc.options.keyRight.setDown(false);
                            currentState = State.RETURNING_TO_ORIGIN;
                            lastStartedReturningToOriginTime = System.currentTimeMillis();
                            break;
                        }
                    } else {
                        if (player.getX() <= originX.get() + 0.3 + 0.001) {
                            mc.options.keyRight.setDown(false);
                            currentRowZ += 3;
                            currentState = State.CHANGING_LANE_ADVANCE;
                            break;
                        }
                    }

                    if (!ensureHoldingCocoa(player) || player.getBlockX() == lastFinishedBlockX) {
                        break;
                    }

                    if (System.currentTimeMillis() - lastPlantTime > 25) {
                        performPlanting(mc, player, true);
                        if (plantStage >= 4) {
                            plantStage = 0;
                            lastFinishedBlockX = player.getBlockX();
                        }
                    }
                    break;

                case CHANGING_LANE_STRAFE:
                    final double targetStrafeZ = currentRowZ + 1 - 0.3;
                    if (player.getZ() >= targetStrafeZ - 0.001) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.PLANTING_RETURN;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case CHANGING_LANE_ADVANCE:
                    final double targetAdvanceZ = currentRowZ - 0.488;
                    if(player.getZ() >= targetAdvanceZ - 0.01) {
                        mc.options.keyRight.setDown(false);
                        currentState = State.DEPOSITING_LEFTOVERS;
                        return;
                    }
                    if (player.getYRot() != -90f) player.setYRot(-90f);
                    if (!mc.options.keyRight.isDown()) mc.options.keyRight.setDown(true);
                    break;

                case RETURNING_TO_ORIGIN:
                    if (System.currentTimeMillis() - lastStartedReturningToOriginTime < 30000){
                        break;
                    }
                    final double targetReturnZ = originZ.get() - 0.7;
                    if (player.getZ() <= targetReturnZ + 0.01) {
                        mc.options.keyUp.setDown(false);
                        justReturnedToOrigin = true;
                        currentState = State.WAITING_FOR_HARVEST;
                        if (currentRowZ != originZ.get()) currentRowZ = originZ.get();
                        return;
                    }
                    if (player.getYRot() != -180f) player.setYRot(-180f);
                    if (!mc.options.keyUp.isDown()) mc.options.keyUp.setDown(true);
                    break;
            }
        }

        // --- Helper Methods ---

        private static void handleDepositingLeftovers(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedChestForDepositing = true;
                boolean hasCocoa = false;
                for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
                    if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                        hasCocoa = true;
                        int slotId = getContainerSlotFromInventory(player, i);
                        if(slotId != -1) {
                            clickSlot(mc, slotId, ClickType.QUICK_MOVE);
                            return; // Do one move per tick
                        }
                    }
                }
                if (!hasCocoa) player.closeContainer();
            } else {
                if (hasOpenedChestForDepositing) {
                    hasOpenedChestForDepositing = false;
                    currentState = State.TAKING_COCOA;
                    return;
                }
                if (player.getYRot() != 45f) player.setYRot(45f);
                if (player.getXRot() != 0f) player.setXRot(0f);
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.CHEST)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void handleTakingCocoa(Minecraft mc, LocalPlayer player) {
            if (mc.screen instanceof AbstractContainerScreen) {
                hasOpenedChestForTaking = true;
                if (System.currentTimeMillis() - lastInventoryActionTime < 150) return;

                if (!player.containerMenu.getCarried().isEmpty()) {
                    int targetHotbarSlot = findAvailableHotbarSlot(player);
                    if (targetHotbarSlot != -1) {
                        int containerSlot = getContainerSlotFromInventory(player, targetHotbarSlot);
                        clickSlot(mc, containerSlot);
                    } else {
                        player.closeContainer();
                    }
                    return;
                }

                int slotToClear = findSlotToClearInHotbar(player);
                if (slotToClear != -1) {
                    int containerSlot = getContainerSlotFromInventory(player, slotToClear);
                    clickSlot(mc, containerSlot, ClickType.QUICK_MOVE);
                    return;
                }

                if (countFullCocoaStacksInHotbar(player) < 8) {
                    int sourceChestSlot = findFullCocoaStackInChest(player);
                    if (sourceChestSlot != -1) {
                        clickSlot(mc, sourceChestSlot, ClickType.QUICK_MOVE);
                        return;
                    }
                }
                player.closeContainer();
            } else {
                if (hasOpenedChestForTaking) {
                    if (System.currentTimeMillis() - lastInventoryActionTime < 250) return;
                    hasOpenedChestForTaking = false;

                    if (player.getInventory().contains(new ItemStack(Items.COCOA_BEANS))) {
                        if (justReturnedToOrigin) justReturnedToOrigin = false;
                        currentState = State.PLANTING;
                    } else {
                        reset();
                    }
                    return;
                }

                float targetYaw;
                float targetPitch;

                // Case 1: Is this the last row?
                if (currentRowZ + 3 >= farmMaxZ.get()) {
                    targetYaw = -68.6f;
                    targetPitch = 44.5f;
                }
                // Case 2: Is this the first row of a new cycle? (or the very first start)
                else if (justReturnedToOrigin || !initialized) {
                    targetYaw = 21.2f;
                    targetPitch = 47.9f;
                }
                // Case 3: All other intermediate rows
                else {
                    targetYaw = 0f;
                    targetPitch = 50f;
                }

                if (player.getYRot() != targetYaw) player.setYRot(targetYaw);
                if (player.getXRot() != targetPitch) player.setXRot(targetPitch);
                if (mc.hitResult instanceof BlockHitResult blockHitResult) {
                    if (mc.level.getBlockState(blockHitResult.getBlockPos()).is(Blocks.BARREL)) {
                        mc.gameMode.useItemOn(player, player.getUsedItemHand(), blockHitResult);
                    }
                }
            }
        }

        private static void clickSlot(Minecraft mc, int slotId) {
            clickSlot(mc, slotId, ClickType.PICKUP);
        }

        private static void clickSlot(Minecraft mc, int slotId, ClickType type) {
            mc.gameMode.handleInventoryMouseClick(mc.player.containerMenu.containerId, slotId, 0, type, mc.player);
            lastInventoryActionTime = System.currentTimeMillis();
        }

        private static boolean ensureHoldingCocoa(LocalPlayer player) {
            if (player.getMainHandItem().is(Items.COCOA_BEANS)) return true;
            for (int i = 0; i < 9; i++) {
                if (player.getInventory().getItem(i).is(Items.COCOA_BEANS)) {
                    player.getInventory().selected = i;
                    return true;
                }
            }
            return false;
        }

        private static int findAvailableHotbarSlot(LocalPlayer player) {
            for (int i = 0; i < 8; i++) {
                if (player.getInventory().getItem(i).isEmpty()) return i;
            }
            return -1;
        }

        private static int findSlotToClearInHotbar(LocalPlayer player) {
            for (int i = 0; i < 8; i++) {
                ItemStack stack = player.getInventory().getItem(i);
                if (!stack.isEmpty() && (!stack.is(Items.COCOA_BEANS) || stack.getCount() < 64)) {
                    return i;
                }
            }
            return -1;
        }

        private static int countFullCocoaStacksInHotbar(LocalPlayer player) {
            int count = 0;
            for(int i = 0; i < 8; i++) {
                ItemStack stack = player.getInventory().getItem(i);
                if (stack.is(Items.COCOA_BEANS) && stack.getCount() == 64) {
                    count++;
                }
            }
            return count;
        }

        private static int findFullCocoaStackInChest(LocalPlayer player) {
            int chestSlotCount = player.containerMenu.slots.size() - player.getInventory().getContainerSize();
            for (int i = 0; i < chestSlotCount; i++) {
                ItemStack stack = player.containerMenu.slots.get(i).getItem();
                if (stack.is(Items.COCOA_BEANS) && stack.getCount() == 64) {
                    return i;
                }
            }
            return -1;
        }

        private static int getContainerSlotFromInventory(LocalPlayer player, int inventorySlot) {
            for (int i = 0; i < player.containerMenu.slots.size(); i++) {
                var slot = player.containerMenu.slots.get(i);
                if (slot.container == player.getInventory() && slot.getContainerSlot() == inventorySlot) {
                    return i;
                }
            }
            return -1;
        }

        private static void performPlanting(Minecraft mc, LocalPlayer player, boolean isReturn) {
            BlockPos logPos;
            float pitch;
            Direction hitDirection;
            Vec3 hitVec;

            if (isReturn) {
                switch(plantStage) {
                    case 0: logPos = player.blockPosition().south().above(5); pitch = -85.3f; break;
                    case 1: logPos = player.blockPosition().south().above(4); pitch = -83f;   break;
                    case 2: logPos = player.blockPosition().south().above(3); pitch = -80f;   break;
                    case 3: logPos = player.blockPosition().south().above(2); pitch = -60f;   break;
                    default: return;
                }
                hitDirection = Direction.NORTH;
                hitVec = new Vec3(logPos.getX() + 0.5, logPos.getY() + 0.5, logPos.getZ());
            } else {
                switch(plantStage) {
                    case 0: logPos = player.blockPosition().north().above(5); pitch = -82f; break;
                    case 1: logPos = player.blockPosition().north().above(4); pitch = -80f;   break;
                    case 2: logPos = player.blockPosition().north().above(3); pitch = -73f;   break;
                    case 3: logPos = player.blockPosition().north().above(2); pitch = -60f;   break;
                    default: return;
                }
                hitDirection = Direction.SOUTH;
                hitVec = new Vec3(logPos.getX() + 0.5, logPos.getY() + 0.5, logPos.getZ() + 1.0);
            }

            player.setXRot(pitch);

            if (mc.level.getBlockState(logPos).is(BlockTags.JUNGLE_LOGS)) {
                BlockHitResult hitResult = new BlockHitResult(hitVec, hitDirection, logPos, false);
                mc.gameMode.useItemOn(player, InteractionHand.MAIN_HAND, hitResult);
            }

            plantStage++;
            lastPlantTime = System.currentTimeMillis();
        }
    }
}
Какой должна быть ферма:

Посмотреть вложение 316457
Ну молодец,реально полезная вещь,очень круто.
 
А, забыл добавить, что там куча задержек потому что фантайм начинает искуственно залагивать гуишки если их слишком часто открывать
 
Назад
Сверху Снизу