From 42771686c6534cdebb4205597311c7011d192f55 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Wed, 12 Jul 2023 16:42:14 -0400 Subject: [PATCH] auto swap elytra --- src/api/java/baritone/api/Settings.java | 15 +++++ .../baritone/behavior/ElytraBehavior.java | 55 +++++++++++++++++++ .../elytra/NetherPathfinderContext.java | 10 ++-- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 08fe54d3a..3f039fe91 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1394,6 +1394,21 @@ public final class Settings { */ public final Setting elytraNetherSeed = new Setting<>(146008555100680L); + /** + * Automatically swap the current elytra with a new one when the durability gets too low + */ + public final Setting elytraAutoSwap = new Setting<>(true); + + /** + * The minimum durability an elytra can have before being swapped + */ + public final Setting elytraMinimumDurability = new Setting<>(5); + + /** + * The number of ticks between doing inventory clicks + */ + public final Setting elytraInventoryTicks = new Setting<>(5); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 7fc47032b..c39950f33 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -51,10 +51,12 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.init.Items; +import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketPlayerPosLook; import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -115,6 +117,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Solution pendingSolution; private boolean solveNextTick; + // auto swap + private int tickCounter; + private int tickLastTransaction = -Baritone.settings().elytraInventoryTicks.value; + private final Queue transactionQueue = new LinkedList<>(); + private ElytraBehavior(Baritone baritone) { super(baritone); this.clearLines = new CopyOnWriteArrayList<>(); @@ -585,6 +592,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } + trySwapElytra(); + if (ctx.player().collidedHorizontally) { logDirect("hbonk"); } @@ -1248,6 +1257,50 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); } + private void tickInventoryTransactions() { + if (tickCounter - tickLastTransaction > Baritone.settings().elytraInventoryTicks.value) { + Runnable r = transactionQueue.poll(); + if (r != null) { + r.run(); + tickLastTransaction = tickCounter; + } + } + tickCounter++; + } + + private void queueWindowClick(int windowId, int slotId, int button, ClickType type) { + transactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, type, ctx.player())); + } + + private int findGoodElytra() { + NonNullList invy = ctx.player().inventory.mainInventory; + for (int i = 0; i < invy.size(); i++) { + ItemStack slot = invy.get(i); + if (slot.getItem() == Items.ELYTRA && (slot.getItem().getMaxDamage() - slot.getItemDamage()) > Baritone.settings().elytraMinimumDurability.value) { + return i; + } + } + return -1; + } + + private void trySwapElytra() { + if (!Baritone.settings().elytraAutoSwap.value) return; + if (!transactionQueue.isEmpty()) return; + + ItemStack chest = ctx.player().inventory.armorInventory.get(2); + if (chest.getItem() != Items.ELYTRA) return; + if (chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) return; + + int goodElytraSlot = findGoodElytra(); + if (goodElytraSlot != -1) { + final int CHEST_SLOT = 6; + final int slotId = goodElytraSlot < 9 ? goodElytraSlot + 36 : goodElytraSlot; + queueWindowClick(ctx.player().inventoryContainer.windowId, slotId, 0, ClickType.PICKUP); + queueWindowClick(ctx.player().inventoryContainer.windowId, CHEST_SLOT, 0, ClickType.PICKUP); + queueWindowClick(ctx.player().inventoryContainer.windowId, slotId, 0, ClickType.PICKUP); + } + } + /** * Minecraft 1.12's pushOutOfBlocks logic doesn't account for players being able to fit under single block spaces, * so whenever the edge of a ceiling is encountered while elytra flying it tries to push the player out. @@ -1331,6 +1384,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } + tickInventoryTransactions(); + if (ctx.player().isElytraFlying()) { this.state = State.FLYING; this.goal = null; diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 9bbb2a24a..063082afb 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -199,12 +199,10 @@ public final class NetherPathfinderContext { } else { id = (int) ((jl | longArray[k] << (64 - l)) & maxEntryValue); } - Octree.setBlock(ptr, - ((idx & 255) & 15), - yReal + (idx >> 8), - ((idx & 255) >> 4), - id != airId - ); + int x = (idx & 15); + int y = yReal + (idx >> 8); + int z = ((idx >> 4) & 15); + Octree.setBlock(ptr, x, y, z, id != airId); } } Octree.setIsFromJava(ptr);