From f559e45f9c237039ed6fce380b37157d9b34a7d8 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Wed, 1 Aug 2018 11:34:35 -0400 Subject: [PATCH] First commit --- Baritone.java | 453 +++++++++++++ inventory/AnotherStealer.java | 193 ++++++ inventory/CraftingTask.java | 694 ++++++++++++++++++++ inventory/FoodManager.java | 74 +++ inventory/InventoryManager.java | 628 ++++++++++++++++++ inventory/SmeltingTask.java | 569 ++++++++++++++++ mining/MickeyMine.java | 464 +++++++++++++ movement/Combat.java | 261 ++++++++ movement/MovementManager.java | 202 ++++++ movement/Parkour.java | 72 ++ pathfinding/Node.java | 58 ++ pathfinding/Path.java | 269 ++++++++ pathfinding/PathFinder.java | 268 ++++++++ pathfinding/actions/Action.java | 211 ++++++ pathfinding/actions/ActionBridge.java | 178 +++++ pathfinding/actions/ActionClimb.java | 107 +++ pathfinding/actions/ActionDescend.java | 40 ++ pathfinding/actions/ActionDescendThree.java | 36 + pathfinding/actions/ActionDescendTwo.java | 36 + pathfinding/actions/ActionFall.java | 47 ++ pathfinding/actions/ActionPillar.java | 141 ++++ pathfinding/actions/ActionPlaceOrBreak.java | 221 +++++++ pathfinding/actions/ActionWalkDiagonal.java | 61 ++ pathfinding/goals/Goal.java | 31 + pathfinding/goals/GoalBlock.java | 68 ++ pathfinding/goals/GoalComposite.java | 59 ++ pathfinding/goals/GoalGetToBlock.java | 31 + pathfinding/goals/GoalRunAway.java | 52 ++ pathfinding/goals/GoalTwoBlocks.java | 42 ++ pathfinding/goals/GoalXZ.java | 68 ++ pathfinding/goals/GoalYLevel.java | 32 + schematic/Schematic.java | 118 ++++ schematic/SchematicBuilder.java | 69 ++ schematic/SchematicLoader.java | 77 +++ strategy/EarlyGameStrategy.java | 304 +++++++++ ui/AimBow.java | 153 +++++ ui/GuiEscMenu.java | 93 +++ ui/LookManager.java | 345 ++++++++++ ui/PathRenderer.java | 248 +++++++ ui/Screenshot.java | 257 ++++++++ util/Autorun.java | 47 ++ util/BlockPuncher.java | 48 ++ util/ChatCommand.java | 436 ++++++++++++ util/FakeArrow.java | 343 ++++++++++ util/MCEdit.java | 69 ++ util/Manager.java | 114 ++++ util/ManagerTick.java | 23 + util/Memory.java | 402 ++++++++++++ util/Out.java | 123 ++++ util/ToolSet.java | 107 +++ 50 files changed, 9042 insertions(+) create mode 100644 Baritone.java create mode 100644 inventory/AnotherStealer.java create mode 100644 inventory/CraftingTask.java create mode 100644 inventory/FoodManager.java create mode 100644 inventory/InventoryManager.java create mode 100644 inventory/SmeltingTask.java create mode 100644 mining/MickeyMine.java create mode 100644 movement/Combat.java create mode 100644 movement/MovementManager.java create mode 100644 movement/Parkour.java create mode 100644 pathfinding/Node.java create mode 100644 pathfinding/Path.java create mode 100644 pathfinding/PathFinder.java create mode 100644 pathfinding/actions/Action.java create mode 100644 pathfinding/actions/ActionBridge.java create mode 100644 pathfinding/actions/ActionClimb.java create mode 100644 pathfinding/actions/ActionDescend.java create mode 100644 pathfinding/actions/ActionDescendThree.java create mode 100644 pathfinding/actions/ActionDescendTwo.java create mode 100644 pathfinding/actions/ActionFall.java create mode 100644 pathfinding/actions/ActionPillar.java create mode 100644 pathfinding/actions/ActionPlaceOrBreak.java create mode 100644 pathfinding/actions/ActionWalkDiagonal.java create mode 100644 pathfinding/goals/Goal.java create mode 100644 pathfinding/goals/GoalBlock.java create mode 100644 pathfinding/goals/GoalComposite.java create mode 100644 pathfinding/goals/GoalGetToBlock.java create mode 100644 pathfinding/goals/GoalRunAway.java create mode 100644 pathfinding/goals/GoalTwoBlocks.java create mode 100644 pathfinding/goals/GoalXZ.java create mode 100644 pathfinding/goals/GoalYLevel.java create mode 100644 schematic/Schematic.java create mode 100644 schematic/SchematicBuilder.java create mode 100644 schematic/SchematicLoader.java create mode 100644 strategy/EarlyGameStrategy.java create mode 100644 ui/AimBow.java create mode 100644 ui/GuiEscMenu.java create mode 100644 ui/LookManager.java create mode 100644 ui/PathRenderer.java create mode 100644 ui/Screenshot.java create mode 100644 util/Autorun.java create mode 100644 util/BlockPuncher.java create mode 100644 util/ChatCommand.java create mode 100644 util/FakeArrow.java create mode 100644 util/MCEdit.java create mode 100644 util/Manager.java create mode 100644 util/ManagerTick.java create mode 100644 util/Memory.java create mode 100644 util/Out.java create mode 100644 util/ToolSet.java diff --git a/Baritone.java b/Baritone.java new file mode 100644 index 00000000..46f419c5 --- /dev/null +++ b/Baritone.java @@ -0,0 +1,453 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone; + +import baritone.movement.Combat; +import baritone.movement.MovementManager; +import baritone.pathfinding.Path; +import baritone.pathfinding.PathFinder; +import baritone.pathfinding.actions.Action; +import baritone.pathfinding.actions.ActionPlaceOrBreak; +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.goals.GoalComposite; +import baritone.schematic.SchematicBuilder; +import baritone.ui.LookManager; +import baritone.util.Autorun; +import baritone.util.Manager; +import baritone.util.ManagerTick; +import baritone.util.Memory; +import baritone.util.Out; +import baritone.util.ToolSet; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * + * @author leijurv + */ +public class Baritone { + + public static BlockPos playerFeet = null; + public static World world = null; + + public static boolean allowDiagonal = true; + public static boolean farf5 = false; + public static boolean slowPath = false; + public static boolean pause = false; + public static boolean overrideF3 = false; + public static boolean sketchytracer = false; + public static boolean allowVerticalMotion = true; + public static boolean actuallyPutMessagesInChat = false; + public static boolean isThereAnythingInProgress = false; + public static boolean fullBright = true; + public static boolean plsCancel = false; + public static int tickNumber = 0; + public static boolean ticktimer = false; + public static boolean allowBreakOrPlace = true; + public static boolean hasThrowaway = true; + public static Path currentPath = null; + public static Path nextPath = null; + public static boolean calculatingNext = false; + public static Goal goal = null; + static int numTicksInInventoryOrCrafting = 0; + public static BlockPos death; + public static long lastDeath = 0; + public static SchematicBuilder currentBuilder = null; + + public static void main(String[] args) throws IOException, InterruptedException { + String s = Autorun.class.getProtectionDomain().getCodeSource().getLocation().toString().substring(5) + "../../autorun/runmc.command"; + if (s.contains("jar")) { + Autorun.start(args); + return; + } + Autorun.runprocess("/usr/local/bin/ant jar"); + Autorun.runprocess("java -Djava.library.path=jars/versions/1.12.2/1.12.2-natives/ -jar dist/Baritone.jar"); + } + + public static IBlockState get(BlockPos pos) { // wrappers for future 1.13 compat + return world.getBlockState(pos); + } + + public static Block getBlock(BlockPos pos) { + return get(pos).getBlock(); + } + + /** + * Called by minecraft.java + */ + public static void onTick() { + try { + long start = System.currentTimeMillis(); + onTick1(); + long end = System.currentTimeMillis(); + long time = end - start; + if (ticktimer && time > 3) { + Out.gui("Tick took " + time + "ms", Out.Mode.Debug); + Out.log("Tick took " + time + "ms"); + } + } catch (Exception ex) { + Out.log("Exception"); + Logger.getLogger(Baritone.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public static void onTick1() { + if (pause) { + Manager.tick(LookManager.class, true); + MovementManager.clearMovement(); + return; + } + world = Minecraft.getMinecraft().world; + if (world == null || Minecraft.getMinecraft().player == null) { + Baritone.cancelPath(); + Baritone.plsCancel = true; + return; + } + MovementManager.leftPressTime = 0; + MovementManager.rightPressTime = 0; + if (MovementManager.isLeftClick) { + MovementManager.leftPressTime = 5; + } + if (MovementManager.isRightClick) { + MovementManager.rightPressTime = 5; + } + Manager.tick(LookManager.class, true); + + /*MovementManager.isLeftClick = false; + MovementManager.isRightClick = false; + MovementManager.jumping = false; + MovementManager.sneak = false;*/ + MovementManager.clearMovement(); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + World theWorld = Minecraft.getMinecraft().world; + playerFeet = new BlockPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + if (thePlayer.isDead && System.currentTimeMillis() > lastDeath + 10000) { + death = playerFeet; + lastDeath = System.currentTimeMillis(); + Out.gui("Saved death position (" + death + "). do /death to set goal.", Out.Mode.Minimal); + //impact handles this + //thePlayer.respawnPlayer(); + //Minecraft.getMinecraft().displayGuiScreen(null); + } + tickNumber++; + hasThrowaway = ActionPlaceOrBreak.hasthrowaway(); + ManagerTick.tickPath = true; + Manager.tick(LookManager.class); + + BlockPos ts = whatAreYouLookingAt(); + if (ts != null) { + Memory.scanBlock(ts); + } + if (currentBuilder != null) { + currentBuilder.tick(); + } + if (currentPath != null && ManagerTick.tickPath) { + if (currentPath.tick()) { + Goal currentPathGoal = currentPath == null ? null : currentPath.goal; + if (currentPath != null && currentPath.failed) { + clearPath(); + Out.gui("Recalculating because path failed", Out.Mode.Standard); + nextPath = null; + if (isAir(playerFeet.down())) {//sometimes we are jumping and we make a path that starts in the air and then jumps up, which is impossible + Out.gui("DOING THE JANKY THING, WARNING", Out.Mode.Debug); + findPathInNewThread(playerFeet.down(), true); + } else { + findPathInNewThread(playerFeet, true); + } + return; + } else { + clearPath(); + } + currentPath = null; + if (goal.isInGoal(playerFeet)) { + Out.gui("All done. At goal", Out.Mode.Standard); + nextPath = null; + } else { + Out.gui("Done with segment", Out.Mode.Debug); + if (nextPath != null || calculatingNext) { + if (calculatingNext) { + calculatingNext = false; + Out.gui("Patiently waiting to finish", Out.Mode.Debug); + } else { + currentPath = nextPath; + nextPath = null; + if (!currentPath.start.equals(playerFeet)) { + //Out.gui("The next path starts at " + currentPath.start + " but I'm at " + playerFeet + ". not doing it", true); + currentPath = null; + findPathInNewThread(playerFeet, true); + } else { + Out.gui("Going onto next", Out.Mode.Debug); + if (!currentPath.goal.isInGoal(currentPath.end)) { + planAhead(); + } + } + } + } else { + Out.gui("Hmm. I'm not actually at the goal. Recalculating.", Out.Mode.Debug); + findPathInNewThread(playerFeet, (currentPathGoal != null && goal != null) ? !(currentPathGoal instanceof GoalComposite) && currentPathGoal.toString().equals(goal.toString()) : true); + } + } + } else { + if (Action.isWater(theWorld.getBlockState(playerFeet).getBlock())) { + //if (Action.isWater(theWorld.getBlockState(playerFeet.down()).getBlock()) || !Action.canWalkOn(playerFeet.down()) || Action.isWater(theWorld.getBlockState(playerFeet.up()).getBlock())) { + //if water is deeper than one block, or we can't walk on what's below the water, or our head is in water, jump + Out.log("Jumping because in water"); + MovementManager.jumping = true; + //} + } + if (nextPath != null) { + for (int i = 1; i < 20 && i < nextPath.path.size(); i++) { + if (playerFeet.equals(nextPath.path.get(i))) { + Out.gui("Jumping to position " + i + " in nextpath", Out.Mode.Debug); + currentPath = nextPath; + currentPath.calculatePathPosition(); + nextPath = null; + if (!currentPath.goal.isInGoal(currentPath.end)) { + planAhead(); + } + break; + } + } + } + LookManager.nudgeToLevel(); + } + } + /*if (Minecraft.getMinecraft().currentScreen != null && (Minecraft.getMinecraft().currentScreen instanceof GuiCrafting || Minecraft.getMinecraft().currentScreen instanceof GuiInventory || Minecraft.getMinecraft().currentScreen instanceof GuiFurnace)) { + MovementManager.isLeftClick = false; + MovementManager.leftPressTime = -5; + numTicksInInventoryOrCrafting++; + if (numTicksInInventoryOrCrafting > 20 * 20) { + Minecraft.getMinecraft().player.closeScreen(); + numTicksInInventoryOrCrafting = 0; + } + } else { + numTicksInInventoryOrCrafting = 0; + }*/ // impact does this + if (isThereAnythingInProgress && Action.isWater(theWorld.getBlockState(playerFeet).getBlock())) { + if (Action.isWater(theWorld.getBlockState(playerFeet.down()).getBlock()) || !Action.canWalkOn(playerFeet.down()) || Action.isWater(theWorld.getBlockState(playerFeet.up()).getBlock())) { + //if water is deeper than one block, or we can't walk on what's below the water, or our head is in water, jump + Out.log("Jumping because in water and pathfinding"); + MovementManager.jumping = true; + } + } + Manager.tick(LookManager.class, false); + } + + public static boolean isPathFinding() { + return isThereAnythingInProgress; + } + + /** + * Clears movement, clears the current path, and lets go of left click. It + * purposefully does NOT clear nextPath. + */ + public static void clearPath() { + currentPath = null; + MovementManager.letGoOfLeftClick(); + MovementManager.clearMovement(); + } + + public static String info(BlockPos bp) { + IBlockState state = get(bp); + Block block = state.getBlock(); + return bp + " " + block + " can walk on: " + Action.canWalkOn(bp) + " can walk through: " + Action.canWalkThrough(bp) + " is full block: " + block.isFullBlock(state) + " is full cube: " + block.isFullCube(state) + " is liquid: " + Action.isLiquid(block) + " is flow: " + Action.isFlowing(bp, state); + } + + /** + * Cancel the path + * + */ + public static void cancelPath() { + nextPath = null; + Combat.target = null; + currentBuilder = null; + clearPath(); + } + + public static boolean isAir(BlockPos pos) { + return Minecraft.getMinecraft().world.getBlockState(pos).getBlock().equals(Block.getBlockById(0)); + } + + public static void findPathInNewThread(final boolean talkAboutIt) { + findPathInNewThread(playerFeet, talkAboutIt); + } + + /** + * In a new thread, pathfind to target blockpos + * + * @param start + * @param talkAboutIt + */ + public static void findPathInNewThread(final BlockPos start, final boolean talkAboutIt) { + if (isThereAnythingInProgress) { + return; + } + isThereAnythingInProgress = true; + new Thread() { + @Override + public void run() { + if (talkAboutIt) { + Out.gui("Starting to search for path from " + start + " to " + goal, Out.Mode.Debug); + } + try { + currentPath = findPath(start); + } catch (Exception e) { + } + isThereAnythingInProgress = false; + if (!currentPath.goal.isInGoal(currentPath.end)) { + if (talkAboutIt) { + Out.gui("I couldn't get all the way to " + goal + ", but I'm going to get as close as I can. " + currentPath.numNodes + " nodes considered", Out.Mode.Standard); + } + planAhead(); + } else if (talkAboutIt) { + Out.gui("Finished finding a path from " + start + " to " + goal + ". " + currentPath.numNodes + " nodes considered", Out.Mode.Debug); + } + } + }.start(); + } + + /** + * In a new thread, pathfind from currentPath.end to goal. Store resulting + * path in nextPath (or in currentPath if calculatingNext was set to false + * in the meantime). + */ + public static void planAhead() { + if (isThereAnythingInProgress) { + return; + } + isThereAnythingInProgress = true; + new Thread() { + @Override + public void run() { + Out.gui("Planning ahead", Out.Mode.Debug); + calculatingNext = true; + Path path = findPath(currentPath.end); + isThereAnythingInProgress = false; + Out.gui("Done planning ahead " + calculatingNext, Out.Mode.Debug); + if (calculatingNext) { + nextPath = path; + } else { + currentPath = path; + if (!plsCancel) { + planAhead(); + } + } + calculatingNext = false; + Out.gui(path.numNodes + " nodes considered, calculated " + path.start + " to " + path.end, Out.Mode.Debug); + } + }.start(); + } + + /** + * Actually do the pathfinding + * + * @param start + * @return + */ + private static Path findPath(BlockPos start) { + if (goal == null) { + Out.gui("babe, please. there is no goal", Out.Mode.Minimal); + return null; + } + try { + PathFinder pf = new PathFinder(start, goal); + Path path = pf.calculatePath(); + return path; + } catch (Exception e) { + Logger.getLogger(Baritone.class.getName()).log(Level.SEVERE, null, e); + isThereAnythingInProgress = false; + return null; + } + } + + /** + * What block is the player looking at + * + * @return the position of it + */ + public static BlockPos whatAreYouLookingAt() { + /*Minecraft mc = Minecraft.getMinecraft(); + if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { + return mc.objectMouseOver.getBlockPos(); + } + return null;*/ + throw new UnsupportedOperationException("need to figure out what MovingObjectPosition is in 1.12.2"); + } + + public static void switchToBestTool() { + BlockPos pos = whatAreYouLookingAt(); + if (pos == null) { + return; + } + Block block = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + if (block.equals(Block.getBlockById(0))) { + return; + } + switchtotool(block); + } + + public static void switchtotool(Block b) { + Baritone.switchtotool(b, new ToolSet()); + } + + public static void switchtotool(Block b, ToolSet ts) { + Minecraft.getMinecraft().player.inventory.currentItem = ts.getBestSlot(b); + } + + public static Entity whatEntityAreYouLookingAt() { + /*Minecraft mc = Minecraft.getMinecraft(); + if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) { + return mc.objectMouseOver.entityHit; + }*/ + throw new UnsupportedOperationException("need to figure out what MovingObjectPosition is in 1.12.2"); + //return null; + } + + public static List getDebugGui() { + if (!overrideF3) { + return null; + } + List list = new ArrayList(); + list.add("§5[§dBaritone§5]§f"); + Class c = LookManager.class; + list.add("§r[§" + (Manager.enabled(c) ? "a" : "c") + c.getSimpleName() + "§r]"); + + list.add(""); + list.add("Current goal: " + goal); + list.add(""); + if (currentPath != null) { + list.add("Current path start: " + currentPath.start); + list.add("Current path end: " + currentPath.end); + list.add("Current path ends in current goal: " + (goal == null ? null : goal.isInGoal(currentPath.end))); + if (!currentPath.goal.equals(goal)) { + list.add("Current path goal: " + currentPath.goal); + } + } + if (nextPath != null) { + list.add(""); + list.add("Next path start: " + nextPath.start); + list.add("Next path end: " + nextPath.end); + list.add("Next path ends in current goal: " + (goal == null ? null : goal.isInGoal(nextPath.end))); + } + return list; + } + + public boolean isNull() throws NullPointerException { + NullPointerException up = new NullPointerException("You are disgusting"); + throw up; + //To use this surround the call to this message with a try-catch then compare the length of the NullPointerException.getMessage() + } +} diff --git a/inventory/AnotherStealer.java b/inventory/AnotherStealer.java new file mode 100644 index 00000000..3adcd76e --- /dev/null +++ b/inventory/AnotherStealer.java @@ -0,0 +1,193 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.inventory; + +import baritone.ui.LookManager; +import baritone.util.Memory; +import java.util.ArrayList; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.pathfinding.goals.GoalComposite; +import baritone.pathfinding.goals.GoalGetToBlock; +import baritone.util.Autorun; +import baritone.util.ChatCommand; +import baritone.util.ChatCommand; +import baritone.util.Manager; +import baritone.util.Manager; +import baritone.util.Memory; +import baritone.util.Out; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author avecowa + */ +public class AnotherStealer extends Manager { + protected static Manager newInstance() { + return null; + } + public static ArrayList alreadyStolenFrom = new ArrayList(); + public static boolean chestStuff = false; + public static boolean stuff = false; + public static BlockPos current = null; + private static final Block CHEST = Block.getBlockFromName("chest"); + private static boolean positionArmor = false; + private static int positionSlot = 0; + private static int positionStatus = 0; + @Override + public void onTick() { + //try{ + if (invFull()) { + ChatCommand.stealer("stealer"); + return; + } + if (Baritone.isThereAnythingInProgress || Baritone.currentPath != null) { + Out.log(Baritone.currentPath); + return; + } + if (stuff) { + stuff = false; + ArrayList chests = Memory.closest(100, "chest"); + chests.removeAll(alreadyStolenFrom); + if (chests.isEmpty()) { + return; + } + BlockPos[] goals = GoalGetToBlock.ajacentBlocks(chests.get(0)); + for (int i = 1; i < chests.size(); i++) { + goals = Autorun.concat(goals, GoalGetToBlock.ajacentBlocks(chests.get(i))); + } + Baritone.goal = new GoalComposite(goals); + ChatCommand.path("path false"); + return; + } + if (positionArmor) { + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiInventory)) { + Out.gui("BAD GUI", Out.Mode.Debug); + positionArmor = false; + return; + } + Out.gui("Position Armor:" + positionSlot, Out.Mode.Debug); + if (positionStatus == 0) { + Container inv = Minecraft.getMinecraft().player.inventoryContainer; + Out.gui("Position Status 0:" + inv.inventorySlots.size(), Out.Mode.Debug); + for (int i = positionSlot; i < 45; i++) { + Out.gui((inv.getSlot(i).getHasStack() ? inv.getSlot(i).getStack().getItem().toString() : "NULL STACK") + " :" + i, Out.Mode.Debug); + if (inv.getSlot(i).getHasStack() && inv.getSlot(i).getStack().getItem() instanceof ItemArmor) { + Out.gui("ITEM IS ARMOR", Out.Mode.Debug); + ItemArmor armor = (ItemArmor) inv.getSlot(i).getStack().getItem(); + if (inv.getSlot(armor.armorType).getHasStack() && ((ItemArmor) inv.getSlot(armor.armorType).getStack().getItem()).damageReduceAmount < armor.damageReduceAmount) { + positionSlot = i; + positionStatus = 1; + Minecraft.getMinecraft().playerController.windowClick(((GuiContainer) Minecraft.getMinecraft().currentScreen).inventorySlots.windowId, 103 - armor.armorType, 0, 1, Minecraft.getMinecraft().player); + return; + } + } + } + positionArmor = false; + Minecraft.getMinecraft().player.closeScreen(); + return; + } + if (positionStatus == 1) { + Minecraft.getMinecraft().playerController.windowClick(((GuiContainer) Minecraft.getMinecraft().currentScreen).inventorySlots.windowId, positionSlot, 0, 1, Minecraft.getMinecraft().player); + positionStatus = 0; + return; + } + } + BlockPos near = getAjacentChest(); + if (near == null) { + stuff = true; + return; + } + if (near.equals(Baritone.whatAreYouLookingAt())) { + if (chestStuff) { + Out.gui("CHEST STUFF", Out.Mode.Debug); + EntityPlayerSP player = Minecraft.getMinecraft().player; + WorldClient world = Minecraft.getMinecraft().world; + if (Minecraft.getMinecraft().currentScreen == null) { + chestStuff = false; + Out.gui("NULL GUI", Out.Mode.Debug); + return; + } + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) { + Out.gui("NOT CHEST GUI", Out.Mode.Debug); + return; + } + GuiChest contain = (GuiChest) Minecraft.getMinecraft().currentScreen; + Slot slot = getFilledSlot(contain); + Out.gui(slot == null ? "null slot" : slot.getHasStack() ? slot.getStack().getItem().toString() : "empty slot", Out.Mode.Debug); + if (slot == null) { + Out.gui("CLOSING THE SCREEN", Out.Mode.Debug); + alreadyStolenFrom.add(near); + positionArmor = true; + positionSlot = 9; + positionStatus = 0; + Baritone.slowOpenInventory(); + return; + } + contain.shiftClick(slot.slotNumber); + return; + } + Out.gui("NO CHEST STUFF", Out.Mode.Debug); + chestStuff = true; + MovementManager.isRightClick = true; + current = Baritone.whatAreYouLookingAt(); + return; + } + LookManager.lookAtBlock(near, true); + return; + } + public static BlockPos getAjacentChest() { + BlockPos[] pos = GoalGetToBlock.ajacentBlocks(Minecraft.getMinecraft().player.getPosition0()); + WorldClient w = Minecraft.getMinecraft().world; + for (BlockPos p : pos) { + if (!alreadyStolenFrom.contains(p) && w.getBlockState(p).getBlock().equals(CHEST)) { + return p; + } + } + return null; + } + public static Slot getFilledSlot(GuiChest chest) { + for (int i = 0; i < chest.lowerChestInventory.getSizeInventory(); i++) { + if (chest.lowerChestInventory.getStackInSlot(i) != null) { + return chest.inventorySlots.getSlotFromInventory(chest.lowerChestInventory, i); + } + } + return null; + } + public static boolean invFull() { + ItemStack[] inv = Minecraft.getMinecraft().player.inventory.mainInventory; + for (ItemStack i : inv) { + if (i == null) { + return false; + } + } + return true; + } + @Override + protected void onCancel() { + } + @Override + protected void onStart() { + alreadyStolenFrom = new ArrayList(); + chestStuff = false; + stuff = false; + current = null; + positionArmor = false; + positionSlot = 0; + } +} diff --git a/inventory/CraftingTask.java b/inventory/CraftingTask.java new file mode 100644 index 00000000..5b5f7558 --- /dev/null +++ b/inventory/CraftingTask.java @@ -0,0 +1,694 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.inventory; + +import java.util.ArrayList; +import java.util.List; +import baritone.inventory.InventoryManager; +import baritone.ui.LookManager; +import baritone.util.Memory; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.mining.MickeyMine; +import baritone.pathfinding.goals.GoalBlock; +import baritone.pathfinding.goals.GoalComposite; +import baritone.util.Manager; +import baritone.util.ManagerTick; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiCrafting; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author galdara + */ +public class CraftingTask extends ManagerTick { + static ArrayList overallCraftingTasks = new ArrayList(); + ArrayList subCraftingTasks = new ArrayList(); + private Item currentlyCrafting = null; + private int stackSize; + private int alreadyHas; + private CraftingTask(ItemStack craftStack) { + this.currentlyCrafting = craftStack.getItem(); + this.stackSize = 0; + buildTasks(); + increaseNeededAmount(craftStack.stackSize); + } + public static int map(int id, int width, int height, int craftingSize) {//shamelessly copied from Objectives + int yPos = id / width; + int xPos = id % width; + int z = xPos + craftingSize * yPos; + return z + 1; + } + /** + * @param item + * @return recipe for that item, or null if item has no recipe + */ + public static IRecipe getRecipeFromItem(Item item) { + List recipes = CraftingManager.getInstance().getRecipeList(); + for (IRecipe currRecipe : recipes) { + if (currRecipe == null) { + continue; + } + if (currRecipe.getRecipeOutput() == null) { + continue; + } + if (currRecipe.getRecipeOutput().getItem() == null) { + continue;//probably not all of these are necessary, but when I added all three it stopped a nullpointerexception somewhere in this function + } + if (currRecipe.getRecipeOutput().getItem().equals(item)) { + if (isRecipeOkay(currRecipe)) { + return currRecipe; + } + } + } + return null; + } + public static boolean isRecipeOkay(IRecipe recipe) { + if (recipe instanceof ShapedRecipes) { + if (((ShapedRecipes) recipe).recipeItems.length > 1) { + return true; + } + for (ItemStack stack : ((ShapedRecipes) recipe).recipeItems) { + if (stack == null) { + continue; + } + if (stack.toString().toLowerCase().contains("block")) { + Out.log("Not doing " + stack); + return false; + } + } + return true; + } + if (recipe instanceof ShapelessRecipes) { + if (((ShapelessRecipes) recipe).recipeItems.size() > 1) { + return true; + } + for (ItemStack stack : ((ShapelessRecipes) recipe).recipeItems) { + if (stack.toString().toLowerCase().contains("block")) { + Out.log("Not doing " + stack); + return false; + } + } + return true; + } + return false; + } + public static boolean recipeNeedsCraftingTable(IRecipe recipe) { + return (recipe instanceof ShapelessRecipes && recipe.getRecipeSize() > 4) || (recipe instanceof ShapedRecipes && (((ShapedRecipes) recipe).recipeHeight > 2 || ((ShapedRecipes) recipe).recipeWidth > 2)); + } + ArrayList plan = null; + int tickNumber = 0; + static int ticksBetweenClicks = 4; + public void tickPlan() { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + if (tickNumber % ticksBetweenClicks == 0) { + int index = tickNumber / ticksBetweenClicks; + if (index >= plan.size()) { + Out.gui("Plan over", Out.Mode.Debug); + plan = null; + tickNumber = -40; + return; + } + if (index >= 0) { + int[] click = plan.get(index); + Out.gui(index + " " + click[0] + " " + click[1] + " " + click[2] + " " + currentlyCrafting(), Out.Mode.Debug); + contain.sketchyMouseClick(click[0], click[1], click[2]); + Out.log("Ticking plan"); + } + } + tickNumber++; + } + public boolean onTick1() { + if (plan != null) { + if (Minecraft.getMinecraft().currentScreen == null || !(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { + plan = null; + tickNumber = 0; + return true; + } + tickPlan(); + return true; + } + if (isDone()) { + return false; + } + if (stackSize != 0) { + Out.log(currentlyCrafting() + " " + alreadyHas + " " + isDone()); + } + boolean hasMaterials = actualDoCraft(1, false, true) != null; + //Out.log("materials " + this + " " + currentlyCrafting() + " " + hasMaterials); + if (!hasMaterials) { + return false; + } + boolean isCraftingTable = Minecraft.getMinecraft().currentScreen != null && Minecraft.getMinecraft().currentScreen instanceof GuiCrafting; + if (isCraftingTable) { + findOrCreateCraftingTask(new ItemStack(Item.getByNameOrId("minecraft:crafting_table"), 0)).clearAll(); + } + if (!recipeNeedsCraftingTable(getRecipeFromItem(currentlyCrafting)) && !isCraftingTable) { + craftAsManyAsICan(true); + return true;//if this doesn't need a crafting table, return no matter what + } + //at this point we know that we need a crafting table + if (isCraftingTable) { + craftAsManyAsICan(false); + return true;//since we are already in a crafting table, return so we don't run the code to get into a crafting table repeatedly + } + if (!recipeNeedsCraftingTable(getRecipeFromItem(currentlyCrafting))) { + return false; + } + //at this point we know that we need a crafting table and we aren't in one at this moment + BlockPos craftingTableLocation = Memory.closestOne("crafting_table"); + if (craftingTableLocation != null) { + MickeyMine.tempDisable = true; + if (LookManager.couldIReach(craftingTableLocation)) { + LookManager.lookAtBlock(craftingTableLocation, true); + if (craftingTableLocation.equals(Baritone.whatAreYouLookingAt())) { + Baritone.currentPath = null; + MovementManager.clearMovement(); + Minecraft.getMinecraft().rightClickMouse(); + findOrCreateCraftingTask(new ItemStack(Item.getByNameOrId("minecraft:crafting_table"), 0)).clearAll(); + } + return true; + } else { + double diffX = craftingTableLocation.getX() + 0.5D - Minecraft.getMinecraft().player.posX; + double diffY = craftingTableLocation.getY() + 0.5D - Minecraft.getMinecraft().player.posY; + double diffZ = craftingTableLocation.getZ() + 0.5D - Minecraft.getMinecraft().player.posZ; + double distXZ = Math.sqrt(diffX * diffX + diffZ * diffZ); + if (distXZ < 50 && Math.abs(diffY) < 20) { + Baritone.goal = new GoalComposite(new GoalBlock(craftingTableLocation.up()), new GoalBlock(craftingTableLocation.north()), new GoalBlock(craftingTableLocation.south()), new GoalBlock(craftingTableLocation.east()), new GoalBlock(craftingTableLocation.west()), new GoalBlock(craftingTableLocation.north().down()), new GoalBlock(craftingTableLocation.south().down()), new GoalBlock(craftingTableLocation.east().down()), new GoalBlock(craftingTableLocation.west().down())); + if (Baritone.currentPath == null && !Baritone.isPathFinding()) { + Baritone.findPathInNewThread(false); + } + return true; + } else { + Out.gui("too far away from closest crafting table (" + distXZ + " blocks), crafting another", Out.Mode.Debug); + } + } + } + if (Baritone.whatAreYouLookingAt() != null && Block.getBlockFromName("crafting_table").equals(Minecraft.getMinecraft().world.getBlockState(Baritone.whatAreYouLookingAt()).getBlock())) { + Baritone.currentPath = null; + MovementManager.clearMovement(); + Minecraft.getMinecraft().rightClickMouse(); + findOrCreateCraftingTask(new ItemStack(Item.getByNameOrId("minecraft:crafting_table"), 0)).clearAll(); + return true; + } + //at this point we know that we need a crafting table and we aren't in one and there isn't one nearby + if (putCraftingTableOnHotBar()) { + MickeyMine.tempDisable = true; + findOrCreateCraftingTask(new ItemStack(Item.getByNameOrId("minecraft:crafting_table"), 0)).clearAll(); + Out.log("Ready to place!"); + if (placeHeldBlockNearby()) { + return true; + } + BlockPos player = Minecraft.getMinecraft().player.getPosition0(); + if (Baritone.isAir(player.down()) || Baritone.isAir(player.up(2))) { + Out.gui("Placing down", Out.Mode.Debug); + LookManager.lookAtBlock(Minecraft.getMinecraft().player.getPosition0().down(), true); + MovementManager.jumping = true; + MovementManager.sneak = true; + if (Minecraft.getMinecraft().player.getPosition0().down().equals(Baritone.whatAreYouLookingAt()) || Minecraft.getMinecraft().player.getPosition0().down().down().equals(Baritone.whatAreYouLookingAt())) { + Minecraft.getMinecraft().rightClickMouse(); + } + return true; + } + /* + LookManager.lookAtBlock(Minecraft.getMinecraft().player.getPosition0().down().north(), true); + LookManager.beSketchy(); + Baritone.forward = new Random().nextBoolean(); + Baritone.backward = new Random().nextBoolean(); + Baritone.left = new Random().nextBoolean(); + Baritone.right = new Random().nextBoolean(); + Baritone.jumping = true;*/ + return true; + } else if (hasCraftingTableInInventory()) { + InventoryManager.putOnHotBar(Item.getByNameOrId("crafting_table")); + return true; + } + //at this point we know that we need a crafting table and we aren't in one and there isn't one nearby and we don't have one + ensureCraftingDesired(Item.getByNameOrId("crafting_table"), 1); + //at this point we know that we need a crafting table and we aren't in one and there isn't one nearby and we don't have one and we don't have the materials to make one + //so just rip at this point + return false; + } + public static boolean placeHeldBlockNearby() { + BlockPos player = Minecraft.getMinecraft().player.getPosition0(); + for (int x = player.getX() - 3; x <= player.getX() + 3; x++) { + for (int y = player.getY() - 2; y <= player.getY() + 1; y++) { + for (int z = player.getZ() - 3; z <= player.getZ() + 3; z++) { + if (x == player.getX() && z == player.getZ()) { + continue; + } + BlockPos pos = new BlockPos(x, y, z); + if (Minecraft.getMinecraft().world.getBlockState(pos).getBlock().equals(Block.getBlockFromName("crafting_table"))) { + Memory.scanBlock(pos); + } + if (Baritone.isAir(pos)) { + for (EnumFacing f : EnumFacing.values()) { + BlockPos placeAgainst = pos.offset(f); + if (!Baritone.isAir(placeAgainst) && Minecraft.getMinecraft().world.getBlockState(placeAgainst).getBlock().isBlockNormalCube()) { + if (LookManager.couldIReach(placeAgainst, f.getOpposite())) { + MovementManager.sneak = true; + double faceX = (pos.getX() + placeAgainst.getX() + 1.0D) * 0.5D; + double faceY = (pos.getY() + placeAgainst.getY()) * 0.5D; + double faceZ = (pos.getZ() + placeAgainst.getZ() + 1.0D) * 0.5D; + if (LookManager.lookAtCoords(faceX, faceY, faceZ, true) && Minecraft.getMinecraft().player.isSneaking()) { + Minecraft.getMinecraft().rightClickMouse(); + } + return true; + } + } + } + } + } + } + } + return false; + } + public static boolean hasCraftingTableInInventory() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (ItemStack item : inv) { + if (item == null) { + continue; + } + if (Item.getByNameOrId("minecraft:crafting_table").equals(item.getItem())) { + return true; + } + } + return false; + } + public static boolean putCraftingTableOnHotBar() {//shamelessly copied from MickeyMine.torch() + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (int i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + continue; + } + if (Item.getByNameOrId("minecraft:crafting_table").equals(item.getItem())) { + p.inventory.currentItem = i; + return true; + } + } + return false; + } + public void clearAll() { + if (stackSize != 0) { + decreaseNeededAmount(stackSize); + } + } + /** + * + * @param inInventory + * @return did I actually craft some + */ + public boolean craftAsManyAsICan(boolean inInventory) { + int amtCurrentlyCraftable = stackSize - alreadyHas; + if (amtCurrentlyCraftable > 64) { + amtCurrentlyCraftable = 64; + } + while (true) { + Boolean b = actualDoCraft(amtCurrentlyCraftable, inInventory, false); + if (b != null) { + return b; + } + amtCurrentlyCraftable--; + if (amtCurrentlyCraftable <= 0) { + return false; + } + } + } + /** + * + * @param outputQuantity + * @param inInventory + * @param justChecking + * @return true if it was able to craft and did, null if it was unable to + * craft because of a lack of input items, false for anything else + * (including being unable to craft for other reasons) + */ + public Boolean actualDoCraft(int outputQuantity, boolean inInventory, boolean justChecking) { + IRecipe currentRecipe = getRecipeFromItem(currentlyCrafting); + int outputVolume = currentRecipe.getRecipeOutput().stackSize; + int inputQuantity = (int) Math.ceil(((double) outputQuantity) / (outputVolume)); + if (currentRecipe instanceof ShapedRecipes) { + ShapedRecipes shaped = (ShapedRecipes) currentRecipe; + if (!inInventory || (inInventory && shaped.recipeHeight <= 2 && shaped.recipeWidth <= 2)) { + int numNotNull = 0; + for (ItemStack recipeItem : shaped.recipeItems) { + if (recipeItem != null) { + numNotNull++; + } + } + Item[] items = new Item[numNotNull]; + int[] positions = new int[items.length]; + int index = 0; + for (int i = 0; i < shaped.recipeItems.length; i++) { + if (shaped.recipeItems[i] == null) { + continue; + } + items[index] = shaped.recipeItems[i].getItem(); + positions[index] = map(i, shaped.recipeWidth, shaped.recipeHeight, inInventory ? 2 : 3); + index++; + } + return actualDoCraftOne(items, positions, inputQuantity, inInventory, justChecking); + } + } + if (currentRecipe instanceof ShapelessRecipes) { + ShapelessRecipes shapeless = (ShapelessRecipes) currentRecipe; + if (!inInventory || (inInventory && shapeless.getRecipeSize() < 4)) { + Item[] items = new Item[shapeless.getRecipeSize()]; + int[] positions = new int[items.length]; + for (int i = 0; i < items.length; i++) { + items[i] = shapeless.recipeItems.get(i).getItem(); + positions[i] = i + 1; + } + return actualDoCraftOne(items, positions, inputQuantity, inInventory, justChecking); + } + } + return justChecking ? null : false; + } + /** + * + * @param items + * @param positions + * @param amount + * @param inv + * @param justChecking + * @return true if it was able to craft and did, null if it was unable to + * craft because of a lack of input items, false for anything else + * (including being unable to craft for other reasons) + */ + public Boolean actualDoCraftOne(Item[] items, int[] positions, int amount, boolean inv, boolean justChecking) { + int[] amounts = new int[items.length]; + for (int i = 0; i < items.length; i++) { + amounts[i] = amount; + } + int[] count = new int[items.length]; + for (ItemStack in : Minecraft.getMinecraft().player.inventory.mainInventory) { + if (in == null) { + continue; + } + Item item = in.getItem(); + int size = in.stackSize; + for (int j = 0; j < items.length; j++) { + if (items[j].equals(item)) { + int amountRemain = amounts[j] - count[j]; + if (amountRemain >= size) { + count[j] += size; + size = 0; + } else { + count[j] += amountRemain; + size -= amountRemain; + } + } + } + } + for (int i = 0; i < count.length; i++) { + if (count[i] != amounts[i]) { + //Out.gui("Not enough " + items[i], true); + return null; + } + } + if (justChecking) { + return false; + } + if (inv) { + if (Minecraft.getMinecraft().currentScreen == null || !(Minecraft.getMinecraft().currentScreen instanceof GuiInventory)) { + Out.log("Opening"); + Baritone.slowOpenInventory(); + } + didIOpenMyInventory = true; + } else if (Minecraft.getMinecraft().currentScreen == null || !(Minecraft.getMinecraft().currentScreen instanceof GuiCrafting)) { + Out.gui("Not in crafting table", Out.Mode.Debug); + return false; + } else { + didIOpenMyInventory = true; + } + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + for (int i = 1; i < (inv ? 5 : 10); i++) { + if (contain.inventorySlots.inventorySlots.get(i).getHasStack()) { + return false; + } + } + Out.gui("Crafting amount " + amount + " of " + currentlyCrafting(), Out.Mode.Debug); + plan = new ArrayList(); + tickNumber = -10; + for (int i = inv ? 9 : 10; i < contain.inventorySlots.inventorySlots.size(); i++) { + Slot slot = contain.inventorySlots.inventorySlots.get(i); + if (!slot.getHasStack()) { + continue; + } + ItemStack in = slot.getStack(); + if (in == null) { + continue; + } + Item item = in.getItem(); + int size = in.stackSize; + for (int j = 0; j < items.length; j++) { + if (amounts[j] <= 0) { + continue; + } + if (items[j].equals(item)) { + leftClick(i); + if (size <= amounts[j]) { + leftClick(positions[j]); + amounts[j] -= size; + size = 0; + } else { + for (int k = 0; k < amounts[j]; k++) { + rightClick(positions[j]); + } + size -= amounts[j]; + leftClick(i); + amounts[j] = 0; + } + } + } + } + Out.gui("shift clicking " + contain.inventorySlots.inventorySlots.get(0).getStack(), Out.Mode.Debug); + shiftClick(0); + for (int i = 0; i < amounts.length; i++) { + if (amounts[i] > 0) { + Out.gui("Not enough " + i + " " + amounts[i] + " " + items[i] + " " + positions[i], Out.Mode.Debug);//this detects if it didn't have enough, but you shouldn't call this function unless you have already made sure you have enough + } + } + return true; + } + public void leftClick(int slot) { + if (!plan.isEmpty()) { + int[] last = plan.get(plan.size() - 1); + if (last[0] == slot && last[1] == 0 && last[2] == 0) { + plan.remove(plan.size() - 1); + return; + } + } + plan.add(new int[]{slot, 0, 0}); + } + public void rightClick(int slot) { + plan.add(new int[]{slot, 1, 0}); + } + public void shiftClick(int slot) { + plan.add(new int[]{slot, 0, 1}); + } + static boolean didIOpenMyInventory = false; + static boolean waitingToClose = false; + static int TUC = 20; + @Override + protected boolean onTick0() { + for (CraftingTask craftingTask : overallCraftingTasks) { + if (craftingTask.plan != null) { + Out.log(craftingTask + " " + craftingTask.currentlyCrafting() + " " + craftingTask.plan); + if (!craftingTask.onTick1()) { + didIOpenMyInventory = true; + } + return true; + } + } + for (CraftingTask craftingTask : overallCraftingTasks) { + if (craftingTask.onTick1()) { + return false; + } + } + if (didIOpenMyInventory) { + waitingToClose = true; + TUC = 3; + didIOpenMyInventory = false; + } + if (waitingToClose) { + TUC--; + if (TUC <= 0) { + Out.gui("Closing screen!!!", Out.Mode.Debug); + Minecraft.getMinecraft().player.closeScreen(); + waitingToClose = false; + TUC = 3; + } + return true; + } + return false; + } + public final void buildTasks() { + IRecipe currentRecipe = getRecipeFromItem(currentlyCrafting); + if (!(currentRecipe == null)) { + if (currentRecipe instanceof ShapedRecipes) { + ShapedRecipes shapedRecipe = (ShapedRecipes) currentRecipe; + for (ItemStack input : shapedRecipe.recipeItems) { + if (input == null) { + continue; + } + IRecipe inputRecipe = getRecipeFromItem(input.getItem()); + if (!(inputRecipe == null)) { + Out.log("As a part of " + currentlyCrafting + ", getting " + input); + CraftingTask newTask = CraftingTask.findOrCreateCraftingTask(new ItemStack(input.getItem(), 0)); + subCraftingTasks.add(newTask); + //newTask.execute(); + } + } + } else if (currentRecipe instanceof ShapelessRecipes) { + ShapelessRecipes shapelessRecipe = (ShapelessRecipes) currentRecipe; + for (ItemStack input : shapelessRecipe.recipeItems) { + IRecipe inputRecipe = getRecipeFromItem(input.getItem()); + if (!(inputRecipe == null)) { + Out.log("As a part of " + currentlyCrafting + ", getting " + input); + CraftingTask newTask = CraftingTask.findOrCreateCraftingTask(new ItemStack(input.getItem(), 0)); + subCraftingTasks.add(newTask); + //newTask.execute(); + } + } + } else { + throw new IllegalStateException("Current recipe isn't shapeless or shaped"); + } + } else { + throw new IllegalArgumentException("no recipe for this"); + } + } + public static CraftingTask findOrCreateCraftingTask(ItemStack itemStack) { + //Out.log("Getting a task for " + itemStack); + for (CraftingTask selectedTask : overallCraftingTasks) { + if (selectedTask.currentlyCrafting().getItem().equals(itemStack.getItem())) { + if (itemStack.stackSize != 0) { + selectedTask.increaseNeededAmount(itemStack.stackSize); + } + return selectedTask; + } + } + CraftingTask newTask = new CraftingTask(itemStack); + overallCraftingTasks.add(newTask); + return newTask; + } + public ItemStack currentlyCrafting() { + return new ItemStack(currentlyCrafting, stackSize); + } + public final void increaseNeededAmount(int amount) { + //Out.gui(currentlyCrafting() + " inc " + amount); + int stackSizeBefore = stackSize; + stackSize += amount; + IRecipe currentRecipe = getRecipeFromItem(currentlyCrafting); + int outputVolume = currentRecipe.getRecipeOutput().stackSize; + int inputQuantityBefore = (int) Math.ceil(((double) stackSizeBefore) / outputVolume); + int inputQuantityNew = (int) Math.ceil(((double) stackSize) / outputVolume); + int change = inputQuantityNew - inputQuantityBefore; + if (change != 0) { + /*for (CraftingTask craftingTask : subCraftingTasks) { + Out.gui("> inc sub " + craftingTask.currentlyCrafting() + " " + change); + }*/ + for (CraftingTask craftingTask : subCraftingTasks) { + craftingTask.increaseNeededAmount(change); + } + } + } + public void decreaseNeededAmount(int amount) { + //Out.gui(currentlyCrafting() + " dec " + amount); + int stackSizeBefore = stackSize; + stackSize -= amount; + IRecipe currentRecipe = getRecipeFromItem(currentlyCrafting); + int outputVolume = currentRecipe.getRecipeOutput().stackSize; + int inputQuantityBefore = (int) Math.ceil(((double) stackSizeBefore) / (outputVolume)); + int inputQuantityNew = (int) Math.ceil(((double) stackSize) / outputVolume); + int change = inputQuantityBefore - inputQuantityNew; + if (change != 0) { + /*for (CraftingTask craftingTask : subCraftingTasks) { + Out.gui("> dec sub " + craftingTask.currentlyCrafting() + " " + change); + }*/ + for (CraftingTask craftingTask : subCraftingTasks) { + craftingTask.decreaseNeededAmount(change); + } + } + } + public void calculateAlreadyHasAmount() { + int count = 0; + for (ItemStack armor : Minecraft.getMinecraft().player.inventory.armorInventory) { + if (armor == null) { + continue; + } + if (currentlyCrafting.equals(armor.getItem())) { + count += armor.stackSize; + } + } + for (int i = 0; i < Minecraft.getMinecraft().player.inventory.getSizeInventory(); i++) { + if (Minecraft.getMinecraft().player.inventory.getStackInSlot(i) == null) { + continue; + } + if (Minecraft.getMinecraft().player.inventory.getStackInSlot(i).getItem().equals(currentlyCrafting)) { + count += Minecraft.getMinecraft().player.inventory.getStackInSlot(i).stackSize; + } + } + alreadyHas = count; + } + public int alreadyHas() { + return alreadyHas; + } + public boolean isDone() { + calculateAlreadyHasAmount(); + return stackSize <= alreadyHas; + } + public static boolean ensureCraftingDesired(Item item, int quantity) { + if (item == null) { + throw new NullPointerException(); + } + CraftingTask craftingTableTask = CraftingTask.findOrCreateCraftingTask(new ItemStack(item, 0)); + //Out.log(craftingTableTask.currentlyCrafting() + " " + quantity + " " + craftingTableTask.stackSize + " " + craftingTableTask.alreadyHas + " " + craftingTableTask.isDone()); + if (craftingTableTask.isDone() && craftingTableTask.alreadyHas >= quantity) { + if (craftingTableTask.stackSize > 0) { + craftingTableTask.decreaseNeededAmount(1); + } + return true; + } + if (craftingTableTask.stackSize < quantity) { + craftingTableTask.increaseNeededAmount(quantity - craftingTableTask.stackSize); + } + return craftingTableTask.alreadyHas >= quantity; + } + public static Manager createInstance(Class c) { + return new CraftingTask(); + } + private CraftingTask() { + } + @Override + protected void onCancel() { + overallCraftingTasks.clear(); + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } +} diff --git a/inventory/FoodManager.java b/inventory/FoodManager.java new file mode 100644 index 00000000..1d101a77 --- /dev/null +++ b/inventory/FoodManager.java @@ -0,0 +1,74 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.inventory; + +import baritone.movement.MovementManager; +import static baritone.Baritone.whatAreYouLookingAt; +import baritone.util.ManagerTick; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemStack; +import net.minecraft.util.FoodStats; + +/** + * + * @author leijurv + */ +public class FoodManager extends ManagerTick { + @Override + protected boolean onTick0() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + FoodStats fs = p.getFoodStats(); + if (!fs.needFood()) { + return false; + } + int foodNeeded = 20 - fs.getFoodLevel(); + boolean anything = foodNeeded >= 3 && Minecraft.getMinecraft().player.getHealth() < 20;//if this is true, we'll just eat anything to get our health up + ItemStack[] inv = p.inventory.mainInventory; + byte slotForFood = -1; + int worst = 10000; + for (byte i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + continue; + } + if (item.getItem() instanceof ItemFood && !item.getItem().getUnlocalizedName(item).equals("item.spiderEye")) { + int healing = ((ItemFood) (item.getItem())).getHealAmount(item); + if (healing <= foodNeeded) {//whatever heals the least. wait that doesn't make sense. idk + slotForFood = i; + } + if (anything && healing > foodNeeded && healing < worst) {//whatever wastes the least + slotForFood = i; + } + } + } + if (slotForFood != -1) { + MovementManager.clearMovement(); + p.inventory.currentItem = slotForFood; + MovementManager.sneak = true; + if (whatAreYouLookingAt() == null) { + MovementManager.isRightClick = true; + } else { + if (p.isSneaking()) {//if we are looking at a block, then sneak because you dont know what right click will do + MovementManager.isRightClick = true; + } + } + return true; + } + return false; + } + @Override + protected void onCancel() { + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } +} diff --git a/inventory/InventoryManager.java b/inventory/InventoryManager.java new file mode 100644 index 00000000..29394ec7 --- /dev/null +++ b/inventory/InventoryManager.java @@ -0,0 +1,628 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.inventory; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Random; +import baritone.Baritone; +import baritone.mining.MickeyMine; +import baritone.util.Manager; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.item.ItemSpade; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class InventoryManager extends Manager { + static HashMap maximumAmounts = null; + static HashMap minimumAmounts = null; + static HashSet onHotbar = new HashSet(); + public static void initMax() { + maximumAmounts = new HashMap(); + minimumAmounts = new HashMap(); + addBounds("cobblestone", 128, 64); + addBounds("coal", 128, 64); + //addBounds("redstone", 0, 0);//no one wants stinking redstone + addBounds("stone", 64, 32); + addBounds("gravel", 64, 32); + addBounds("dirt", 128, 64); + } + public static void addBounds(String itemName, int max, int min) { + Item item = Item.getByNameOrId("minecraft:" + itemName); + if (item == null) { + Out.gui(itemName + " doesn't exist", Out.Mode.Minimal); + throw new NullPointerException(itemName + " doesn't exist"); + } + maximumAmounts.put(itemName, max); + minimumAmounts.put(itemName, min); + } + static boolean openedInvYet = false; + /** + * Place the best instance of itemType in hot bar slot position + * + * @param pos hot bar slot to put in + * @param check what block to check break time against + * @param itemType the class of the item + * @param doThrowaway throw away all but the best two + * @return + */ + public static boolean place(int pos, Block check, Class itemType, boolean doThrowaway) { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + int itemPos = -1; + float bestStrength = Float.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item.getClass() == itemType) { + float strength = item.getStrVsBlock(stack, check); + if (strength > bestStrength) { + bestStrength = strength; + itemPos = i; + } + } + } + if (itemPos == -1) {//there are none + return false; + } + if (itemPos == pos) {//there is one and this is the best + if (!doThrowaway) { + return false; + } + int seconditemPos = -1; + float secondbestStrength = Float.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + if (i == itemPos) { + continue; + } + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item.getClass() == itemType) { + float strength = item.getStrVsBlock(stack, check); + if (strength > secondbestStrength) { + secondbestStrength = strength; + seconditemPos = i; + } + } + } + if (seconditemPos == -1) { + return false; + } + for (int i = 0; i < stacks.length; i++) { + if (i == itemPos || i == seconditemPos) { + continue; + } + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item.getClass() == itemType) { + int j = i; + if (j < 9) { + j += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + dropOne(j); + return true; + } + } + return false; + } + if (itemPos < 9) { + itemPos += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + switchWithHotBar(itemPos, pos); + return true; + } + /** + * Find items in the player's inventory + * + * @param items + * @return + */ + public static int find(Item... items) { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + int bestPosition = -1; + int bestSize = 0; + for (int i = 0; i < stacks.length; i++) { + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + for (Item it : items) { + if (it.equals(stack.getItem())) { + if (stack.stackSize > bestSize) { + bestSize = stack.stackSize; + bestPosition = i; + } + } + } + } + return bestPosition; + } + /** + * Put items in the hot bar slot. If the current item in that slot matches, + * don't do anything + * + * @param hotbarslot + * @param items + * @return + */ + public static boolean putItemInSlot(int hotbarslot, Item... items) { + int currPos = find(items); + ItemStack curr = Minecraft.getMinecraft().player.inventory.mainInventory[hotbarslot]; + if (curr != null) { + for (Item item : items) { + if (item.equals(curr.getItem())) { + return false; + } + } + } + if (currPos == -1) { + return false; + } + if (currPos < 9) { + currPos += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + switchWithHotBar(currPos, hotbarslot); + return true; + } + /** + * Randomize an array. You know I just kinda realized that I don't know who + * originally came up with this method for randomizing arrays. I copied it + * from something we used in Terry G's web programming class when we were + * making the game of 15/16 4x4 square thingy, and we used it to randomize a + * 16 length array. I copied it from there and have been using it ever since + * + * @param array + * @param random + */ + public static void randomize(int[] array, Random random) { + for (int i = 0; i < array.length; i++) { + int j = random.nextInt(array.length); + int tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + } + public static void putOnHotBar(Item item) { + if (item == null) { + throw new NullPointerException(); + } + onHotbar.add(item); + } + @Override + protected void onTick() { + if (maximumAmounts == null) { + initMax(); + } + if (Minecraft.getMinecraft().currentScreen != null && !(Minecraft.getMinecraft().currentScreen instanceof GuiInventory)) { + return; + } + if (openedInvYet && Minecraft.getMinecraft().currentScreen == null) { + openedInvYet = false; + return; + } + BlockPos look = Baritone.whatAreYouLookingAt(); + boolean doThrowAway = true; + if (look != null) { + int xDiff = look.getX() - Minecraft.getMinecraft().player.getPosition0().getX(); + int zDiff = look.getZ() - Minecraft.getMinecraft().player.getPosition0().getZ(); + if (Math.abs(xDiff) + Math.abs(zDiff) <= 2) { + doThrowAway = false;//dont throw away if we are looking at a wall and we are close, because we'll probably just pick it right back up again + } + } + if (checkArmor()) { + return; + } + if (doThrowAway && throwAwayOldArmor()) { + return; + } + Random random = new Random(Minecraft.getMinecraft().player.getName().hashCode()); + int[] slots = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + randomize(slots, random); + if (place(slots[0], Block.getBlockFromName("stone"), ItemPickaxe.class, doThrowAway)) { + return; + } + if (placeSword(slots[1], doThrowAway)) { + return; + } + if (placeFood(slots[2])) { + return; + } + if (place(slots[3], Block.getBlockFromName("log"), ItemAxe.class, doThrowAway)) { + return; + } + if (place(slots[4], Block.getBlockFromName("dirt"), ItemSpade.class, doThrowAway)) { + return; + } + if (putItemInSlot(slots[5], Item.getByNameOrId("minecraft:dirt"), Item.getByNameOrId("minecraft:cobblestone"))) { + return; + } + if (putItemInSlot(slots[6], Item.getByNameOrId("minecraft:torch"))) { + return; + } + if (!onHotbar.isEmpty()) { + Out.gui("Hotbar: " + onHotbar, Out.Mode.Debug); + } + int slotIndex = 7; + for (Item item : onHotbar) { + if (putItemInSlot(slots[slotIndex], item)) { + return; + } + slotIndex++; + if (slotIndex > 8) { + break; + } + } + onHotbar.clear(); + HashMap amounts = countItems(); + for (String itemName : maximumAmounts.keySet()) { + if (!doThrowAway) { + continue; + } + Item item = Item.getByNameOrId("minecraft:" + itemName); + if (amounts.get(item) == null) { + amounts.put(item, 0); + } + //Out.log(amounts.get(item)); + int toThrowAway = amounts.get(item) > maximumAmounts.get(itemName) ? amounts.get(item) - minimumAmounts.get(itemName) : 0; + if (amounts.get(item) <= minimumAmounts.get(itemName)) { + MickeyMine.notifyFullness(itemName, false); + } + if (amounts.get(item) > ((minimumAmounts.get(itemName) + maximumAmounts.get(itemName)) / 2)) { + MickeyMine.notifyFullness(itemName, true); + } + if (toThrowAway <= 0) { + continue; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + GuiContainer c = (GuiContainer) Minecraft.getMinecraft().currentScreen; + if (Minecraft.getMinecraft().currentScreen == null) { + Out.gui("Null container", Out.Mode.Debug); + openedInvYet = false; + return; + } + int bestPos = -1; + int bestSize = 0; + for (int i = 0; i < c.inventorySlots.inventorySlots.size(); i++) { + Slot slot = c.inventorySlots.inventorySlots.get(i); + if (slot == null) { + continue; + } + ItemStack is = slot.getStack(); + if (is == null) { + continue; + } + if (item.equals(is.getItem())) { + if (is.stackSize > bestSize && is.stackSize <= toThrowAway) { + bestSize = is.stackSize; + bestPos = i; + } + } + } + if (bestPos != -1) { + dropAll(bestPos);//throw away the largest stack that's smaller than toThrowAway, if it exists + return; + } + for (int i = 0; i < c.inventorySlots.inventorySlots.size(); i++) { + Slot slot = c.inventorySlots.inventorySlots.get(i); + if (slot == null) { + continue; + } + ItemStack is = slot.getStack(); + if (is == null) { + continue; + } + if (item.equals(is.getItem())) { + if (is.stackSize <= toThrowAway) { + toThrowAway -= is.stackSize; + dropAll(i); + return; + } else { + for (int j = 0; j < toThrowAway; j++) { + dropOne(i); + return; + } + toThrowAway = 0; + } + if (toThrowAway <= 0) { + break; + } + } + } + } + if (openedInvYet) { + Minecraft.getMinecraft().player.closeScreen(); + openedInvYet = false; + } + } + public static HashMap countItems() { + HashMap amounts = new HashMap(); + for (ItemStack is : Minecraft.getMinecraft().player.inventory.mainInventory) { + if (is != null && is.getItem() != null) { + if (amounts.get(is.getItem()) == null) { + amounts.put(is.getItem(), is.stackSize); + } else { + amounts.put(is.getItem(), is.stackSize + amounts.get(is.getItem())); + } + } + } + return amounts; + } + public static boolean placeSword(int slot, boolean doThrowaway) { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + int swordPos = -1; + float bestStrength = Float.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item instanceof ItemSword) { + ItemSword sword = (ItemSword) item; + float strength = sword.getDamageVsEntity(); + if (strength > bestStrength) { + bestStrength = strength; + swordPos = i; + } + } + } + if (swordPos == -1) { + return false; + } + if (swordPos == slot) { + if (!doThrowaway) { + return false; + } + int seconditemPos = -1; + float secondbestStrength = Float.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + if (i == swordPos) { + continue; + } + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item instanceof ItemSword) { + float strength = ((ItemSword) item).getDamageVsEntity(); + if (strength > secondbestStrength) { + secondbestStrength = strength; + seconditemPos = i; + } + } + } + if (seconditemPos == -1) { + return false; + } + for (int i = 0; i < stacks.length; i++) { + if (i == swordPos || i == seconditemPos) { + continue; + } + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item instanceof ItemSword) { + int j = i; + if (j < 9) { + j += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + dropOne(j); + return true; + } + } + return false; + } + if (swordPos < 9) { + swordPos += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + switchWithHotBar(swordPos, slot); + return true; + } + public static boolean placeFood(int slot) { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + int foodPos = -1; + float bestStrength = Float.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item instanceof ItemFood && !item.getUnlocalizedName(stack).equals("item.spiderEye")) { + ItemFood food = (ItemFood) item; + float strength = food.getHealAmount(stack); + if (strength > bestStrength) { + bestStrength = strength; + foodPos = i; + } + } + } + if (foodPos == -1) { + return false; + } + if (foodPos == slot) { + return false; + } + if (foodPos < 9) { + foodPos += 36; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + switchWithHotBar(foodPos, slot); + return true; + } + public static boolean playerHasOpenSlot() { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + for (ItemStack stack : stacks) { + if (stack == null) { + return true; + } + } + return false; + } + public static boolean throwAwayOldArmor() { + for (int i = 0; i < 4; i++) { + int betterInd = bestArmor(i, true); + if (betterInd == -1) { + continue; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + if (betterInd < 9) { + betterInd += 36; + } + dropOne(betterInd); + return true; + } + return false; + } + public static boolean checkArmor() { + //helmet, inv container slot 5, armorType 0, armorInventory 3 + //chestplate, inv container slot 6, armorType 1, armorInventory 2 + //leggings, inv container slot 7, armorType 2, armorInventory 1 + //boots, inv container slot 8, armorType 3, armorInventory 0 + for (int i = 0; i < 4; i++) { + int betterInd = bestArmor(i, false); + if (betterInd == -1) { + continue; + } + if (!openedInvYet) { + Baritone.slowOpenInventory(); + openedInvYet = true; + } + ItemStack currentArmor = Minecraft.getMinecraft().player.inventory.armorInventory[3 - i]; + if (currentArmor != null) { + if (playerHasOpenSlot()) { + shiftClick(i + 5); + return true; + } else { + dropOne(i + 5);//if we don't have space, drop the inferior armor + return true; + } + } + if (betterInd < 9) { + betterInd += 36; + } + shiftClick(betterInd); + return true; + } + return false; + } + public static int bestArmor(int type, boolean onlyMainInv) { + ItemStack[] stacks = Minecraft.getMinecraft().player.inventory.mainInventory; + int bestInd = -1; + int bestDamageReduce = Integer.MIN_VALUE; + for (int i = 0; i < stacks.length; i++) { + ItemStack stack = stacks[i]; + if (stack == null) { + continue; + } + Item item = stack.getItem(); + if (item instanceof ItemArmor) { + ItemArmor armor = (ItemArmor) item; + if (armor.armorType == type) { + if (armor.damageReduceAmount > bestDamageReduce) { + bestDamageReduce = armor.damageReduceAmount; + bestInd = i; + } + } + } + } + if (onlyMainInv) { + return bestInd; + } + ItemStack currentlyInSlot = Minecraft.getMinecraft().player.inventory.armorInventory[3 - type]; + if (currentlyInSlot != null) { + ItemArmor armor = (ItemArmor) currentlyInSlot.getItem(); + if (armor.armorType != type) { + throw new IllegalStateException(currentlyInSlot + " should be " + type + ", is " + armor.armorType); + } + if (armor.damageReduceAmount >= bestDamageReduce) { + return -1;//if we are already wearing better armor, pretend there is no good armor of this type in main inv + } + } + return bestInd; + } + public static void switchWithHotBar(int slotNumber, int hotbarPosition) { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + contain.sketchyMouseClick(slotNumber, hotbarPosition, 2); + } + public static void dropAll(int slotNumber) { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + contain.sketchyMouseClick(slotNumber, 1, 4); + } + public static void dropOne(int slotNumber) { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + contain.sketchyMouseClick(slotNumber, 0, 4); + } + public static void shiftClick(int slotNumber) { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + contain.shiftClick(slotNumber); + } + @Override + protected void onCancel() { + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return Baritone.tickNumber % 10 == 0 && !Minecraft.getMinecraft().player.capabilities.isCreativeMode; + } +} diff --git a/inventory/SmeltingTask.java b/inventory/SmeltingTask.java new file mode 100644 index 00000000..d14195e4 --- /dev/null +++ b/inventory/SmeltingTask.java @@ -0,0 +1,569 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.inventory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import baritone.inventory.InventoryManager; +import baritone.ui.LookManager; +import baritone.util.Memory; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.mining.MickeyMine; +import baritone.pathfinding.goals.GoalBlock; +import baritone.pathfinding.goals.GoalComposite; +import baritone.util.Manager; +import baritone.util.ManagerTick; +import baritone.util.Out; +import static baritone.inventory.CraftingTask.placeHeldBlockNearby; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiFurnace; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class SmeltingTask extends ManagerTick { + static HashMap furnacesInUse = new HashMap();//smelting tasks that have been put in a furnace are here + static ArrayList inProgress = new ArrayList();//all smelting tasks will be in here + public static boolean coalOnly = false; + public static boolean avoidBreaking(BlockPos pos) { + return furnacesInUse.containsKey(pos); + } + public static Manager createInstance(Class c) { + return new SmeltingTask(); + } + private SmeltingTask() { + toPutInTheFurnace = null; + desired = null; + burnTicks = 0; + } + @Override + protected boolean onTick0() { + for (SmeltingTask task : new ArrayList(inProgress)) {//make a copy because of concurrent modification bs + if (task.plan != null) { + task.exec(); + return true; + } + } + for (SmeltingTask task : new ArrayList(inProgress)) {//make a copy because of concurrent modification bs + if (task.exec()) { + return false; + } + } + return false; + } + public static int tasksFor(Item result) { + int sum = 0; + for (SmeltingTask task : inProgress) { + if (result.equals(task.desired.getItem())) { + sum += task.desired.stackSize; + } + } + return sum; + } + public static void clearInProgress() { + for (int i = 0; i < inProgress.size(); i++) { + if (inProgress.get(i).isItDone) { + inProgress.remove(i); + i--; + } + } + } + public static BlockPos getUnusedFurnace() { + BlockPos best = null; + double bestDist = Double.MAX_VALUE; + for (BlockPos pos : Memory.closest(100, "furnace", "lit_furnace")) { + if (furnacesInUse.get(pos) != null) { + continue; + } + double dist = dist(pos); + if (best == null || dist < bestDist) { + bestDist = dist; + best = pos; + } + } + return best; + } + public static double dist(BlockPos pos) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + double diffX = thePlayer.posX - pos.getX(); + double diffY = thePlayer.posY - pos.getY(); + double diffZ = thePlayer.posZ - pos.getZ(); + return Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); + } + private final ItemStack toPutInTheFurnace; + private final ItemStack desired; + private BlockPos furnace = null; + private boolean didIPutItInAlreadyPhrasing = false; + private boolean isItDone = false; + public final int burnTicks; + public SmeltingTask(ItemStack desired) { + toPutInTheFurnace = recipe(desired); + if (toPutInTheFurnace == null) { + String m = "Babe I can't smelt anyting to make " + desired; + Out.gui(m, Out.Mode.Minimal); + throw new IllegalArgumentException(m); + } + burnTicks = toPutInTheFurnace.stackSize * 200; + this.desired = desired; + } + public void begin() { + if (inProgress.contains(this)) { + return; + } + inProgress.add(this); + //todo: merge different smelting tasks for the same item + } + int numTicks = -20;//wait a couple extra ticks, for no reason (I guess server lag maybe) + int guiWaitTicks = 0; + int shiftWaitTicks = 0; + private boolean exec() { + Out.log(didIPutItInAlreadyPhrasing + " " + isItDone + " " + numTicks + " " + burnTicks + " " + furnace + " " + Minecraft.getMinecraft().currentScreen == null); + if (!didIPutItInAlreadyPhrasing && Minecraft.getMinecraft().currentScreen == null) { + BlockPos furnaceLocation = getUnusedFurnace(); + if (furnaceLocation != null) { + if (LookManager.couldIReach(furnaceLocation)) { + LookManager.lookAtBlock(furnaceLocation, true); + if (furnaceLocation.equals(Baritone.whatAreYouLookingAt())) { + furnace = furnaceLocation; + Baritone.currentPath = null; + MovementManager.clearMovement(); + Minecraft.getMinecraft().rightClickMouse(); + } + return true; + } else { + double diffX = furnaceLocation.getX() + 0.5D - Minecraft.getMinecraft().player.posX; + double diffY = furnaceLocation.getY() + 0.5D - Minecraft.getMinecraft().player.posY; + double diffZ = furnaceLocation.getZ() + 0.5D - Minecraft.getMinecraft().player.posZ; + double distXZ = Math.sqrt(diffX * diffX + diffZ * diffZ); + if (distXZ < 50 && Math.abs(diffY) < 20) { + Baritone.goal = new GoalComposite(new GoalBlock(furnaceLocation.up()), new GoalBlock(furnaceLocation.north()), new GoalBlock(furnaceLocation.south()), new GoalBlock(furnaceLocation.east()), new GoalBlock(furnaceLocation.west()), new GoalBlock(furnaceLocation.north().down()), new GoalBlock(furnaceLocation.south().down()), new GoalBlock(furnaceLocation.east().down()), new GoalBlock(furnaceLocation.west().down())); + if (Baritone.currentPath == null && !Baritone.isPathFinding()) { + Baritone.findPathInNewThread(false); + } + return true; + } else { + Out.gui("too far away from closest furnace (" + distXZ + " blocks), crafting another", Out.Mode.Standard); + } + } + } + if (putFurnaceOnHotBar()) { + Out.log("Ready to place!"); + if (placeHeldBlockNearby()) { + return true; + } + BlockPos player = Minecraft.getMinecraft().player.getPosition0(); + if (Baritone.isAir(player.down()) || Baritone.isAir(player.up(2))) { + Out.gui("Placing down", Out.Mode.Debug); + LookManager.lookAtBlock(Minecraft.getMinecraft().player.getPosition0().down(), true); + MovementManager.jumping = true; + if (Minecraft.getMinecraft().player.getPosition0().down().equals(Baritone.whatAreYouLookingAt()) || Minecraft.getMinecraft().player.getPosition0().down().down().equals(Baritone.whatAreYouLookingAt())) { + Minecraft.getMinecraft().rightClickMouse(); + } + return true; + } + return true; + } else if (hasFurnaceInInventory()) { + InventoryManager.putOnHotBar(Item.getByNameOrId("furnace")); + return true; + } + return false; + } + boolean guiOpen = Minecraft.getMinecraft().currentScreen != null && Minecraft.getMinecraft().currentScreen instanceof GuiFurnace; + boolean ret = false; + if (guiOpen) { + guiWaitTicks++; + if (guiWaitTicks < 5) { + guiOpen = false; + } + if (!didIPutItInAlreadyPhrasing) { + if (furnace == null) { + furnace = Baritone.whatAreYouLookingAt(); + } + furnacesInUse.put(furnace, this); + ret = true; + } + } else { + guiWaitTicks = 0; + } + if (guiOpen) { + GuiFurnace contain = (GuiFurnace) Minecraft.getMinecraft().currentScreen; + if (!didIPutItInAlreadyPhrasing) { + Boolean b = realPutItIn_PHRASING(contain); + if (b != null && b) { + didIPutItInAlreadyPhrasing = true; + ret = true;//done + } + if (b == null) { + ret = true;//in progress + } + if (b != null && !b) { + ret = false; + } + } + if (isItDone && furnace.equals(Baritone.whatAreYouLookingAt())) {//if we are done, and this is our furnace + ret = true; + Out.gui("taking it out", Out.Mode.Debug); + if (isEmpty(contain, 2)) {//make sure + if (shiftWaitTicks > 5) { + Minecraft.getMinecraft().player.closeScreen();//close the screen + inProgress.remove(this);//no longer an in progress smelting dask + Out.gui("Smelting " + desired + " totally done m9", Out.Mode.Debug); + return false; + } + shiftWaitTicks++; + } else { + shiftWaitTicks = 0; + if (numTicks % 5 == 0) { + contain.shiftClick(2);//take out the output + } + } + } + } + if (didIPutItInAlreadyPhrasing) { + numTicks++; + if (Memory.blockLoaded(furnace)) { + Block curr = Minecraft.getMinecraft().world.getBlockState(furnace).getBlock(); + if (!Block.getBlockFromName("furnace").equals(curr) && !Block.getBlockFromName("lit_furnace").equals(curr)) { + Out.gui("Furnace at " + furnace + " is now gone. RIP. Was trying to make " + desired + ". Is now " + curr, Out.Mode.Standard); + inProgress.remove(this); + return false; + } + } + if (!isItDone && numTicks >= burnTicks) { + isItDone = true; + Out.gui("Hey we're done. Go to your furnace at " + furnace + " and pick up " + desired, Out.Mode.Debug); + furnacesInUse.put(furnace, null); + } + if (isItDone) { + MickeyMine.tempDisable = true; + } + if (isItDone && !guiOpen) { + if (LookManager.couldIReach(furnace)) { + Baritone.currentPath = null; + MovementManager.clearMovement(); + LookManager.lookAtBlock(furnace, true); + if (furnace.equals(Baritone.whatAreYouLookingAt())) { + Minecraft.getMinecraft().rightClickMouse(); + } + } else { + Baritone.goal = new GoalComposite(new GoalBlock(furnace.up()), new GoalBlock(furnace.north()), new GoalBlock(furnace.south()), new GoalBlock(furnace.east()), new GoalBlock(furnace.west()), new GoalBlock(furnace.north().down()), new GoalBlock(furnace.south().down()), new GoalBlock(furnace.east().down()), new GoalBlock(furnace.west().down())); + if (Baritone.currentPath == null && !Baritone.isThereAnythingInProgress) { + Baritone.findPathInNewThread(false); + } + } + } + if (isItDone && (numTicks - 1) % (60 * 20) == 0) { + Out.gui("DUDE. Go to your furnace at " + furnace + " and pick up " + desired + ". Do /cancelfurnace if you want these notifications to piss off.", Out.Mode.Minimal); + } + } + return ret; + } + public static boolean hasFurnaceInInventory() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (ItemStack item : inv) { + if (item == null) { + continue; + } + if (Item.getByNameOrId("minecraft:furnace").equals(item.getItem())) { + return true; + } + } + return false; + } + public static boolean putFurnaceOnHotBar() {//shamelessly copied from MickeyMine.torch() + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (int i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + continue; + } + if (Item.getByNameOrId("furnace").equals(item.getItem())) { + p.inventory.currentItem = i; + return true; + } + } + return false; + } + public boolean isInFurnace() { + return didIPutItInAlreadyPhrasing; + } + public boolean lookingForFurnace() { + return furnace == null; + } + private ArrayList plan; + int tickNumber = 0; + static int ticksBetweenClicks = 4; + public boolean tickPlan() { + GuiContainer contain = (GuiContainer) Minecraft.getMinecraft().currentScreen; + if (tickNumber % ticksBetweenClicks == 0) { + int index = tickNumber / ticksBetweenClicks; + if (index >= plan.size()) { + if (index >= plan.size() + 2) { + Out.gui("Plan over", Out.Mode.Debug); + plan = null; + tickNumber = -40; + Minecraft.getMinecraft().player.closeScreen(); + return true; + } + tickNumber++; + return false; + } + if (index >= 0) { + int[] click = plan.get(index); + Out.gui(index + " " + click[0] + " " + click[1] + " " + click[2] + " " + desired, Out.Mode.Debug); + contain.sketchyMouseClick(click[0], click[1], click[2]); + Out.log("Ticking plan"); + } + } + tickNumber++; + return false; + } + private Boolean realPutItIn_PHRASING(GuiFurnace contain) {//null: in progress. false: unable. true: done + if (plan == null) { + if (!generatePlan(contain)) { + return false; + } + return null; + } + if (tickPlan()) { + return true; + } + return null; + } + private boolean generatePlan(GuiFurnace contain) { + int desiredAmount = toPutInTheFurnace.stackSize; + if (currentSize1(contain, 0, toPutInTheFurnace.getItem()) == -1) { + Out.gui("Furnace already in use", Out.Mode.Debug); + return false; + } + ArrayList burnableItems = new ArrayList(); + ArrayList burnTimes = new ArrayList(); + ArrayList amountWeHave = new ArrayList(); + ArrayList amtNeeded = new ArrayList(); + for (int i = 3; i < contain.inventorySlots.inventorySlots.size(); i++) { + Slot slot = contain.inventorySlots.inventorySlots.get(i); + if (!slot.getHasStack()) { + continue; + } + ItemStack in = slot.getStack(); + if (in == null) { + continue; + } + Item item = in.getItem(); + int ind = burnableItems.indexOf(item); + if (ind == -1) { + int time = TileEntityFurnace.getItemBurnTime(in); + if (time <= 0) { + Out.gui(in + " isn't fuel, lol", Out.Mode.Standard); + continue; + } + burnableItems.add(in.getItem()); + amountWeHave.add(in.stackSize); + burnTimes.add(time); + int numRequired = (int) Math.ceil(((double) burnTicks) / (time)); + amtNeeded.add(numRequired); + } else { + amountWeHave.set(ind, amountWeHave.get(ind) + in.stackSize); + } + } + for (int i = 0; i < burnableItems.size(); i++) { + if (amountWeHave.get(i) < amtNeeded.get(i)) { + Out.gui("Not using fuel " + burnableItems.get(i) + " because not enough (have " + amountWeHave.get(i) + ", need " + amtNeeded.get(i) + ")", Out.Mode.Standard); + burnableItems.remove(i); + amountWeHave.remove(i); + amtNeeded.remove(i); + burnTimes.remove(i); + i--; + } + } + if (burnableItems.isEmpty()) { + Out.gui("lol no fuel", Out.Mode.Standard); + return false; + } + Out.log(burnableItems); + Out.log(amountWeHave); + Out.log(amtNeeded); + Out.log(burnTimes); + Item bestFuel = null; + int fuelAmt = Integer.MAX_VALUE; + int bestExtra = Integer.MAX_VALUE; + for (int i = 0; i < burnableItems.size(); i++) { + int amt = amtNeeded.get(i); + int extra = burnTimes.get(i) * amtNeeded.get(i) - burnTicks; + boolean better = extra < bestExtra || (extra == bestExtra && amt < fuelAmt); + boolean thisisCoal = Item.getByNameOrId("coal").equals(burnableItems.get(i)); + boolean bestIsCoal = Item.getByNameOrId("coal").equals(bestFuel); + if ((better && !coalOnly) || (coalOnly && ((thisisCoal && !bestIsCoal) || (thisisCoal && bestIsCoal && better) || (!thisisCoal && !bestIsCoal && better)))) { + fuelAmt = amt; + bestExtra = extra; + bestFuel = burnableItems.get(i); + } + } + Out.gui("Using " + fuelAmt + " items of " + bestFuel + ", which wastes " + bestExtra + " ticks of fuel.", Out.Mode.Debug); + int currFuelSize = 0; + if (currentSize1(contain, 1, bestFuel) == -1) { + Out.gui("Furnace already in use", Out.Mode.Debug); + return false; + } + if (currentSize1(contain, 0, toPutInTheFurnace.getItem()) == -1) { + Out.gui("Furnace already in use", Out.Mode.Debug); + return false; + } + plan = new ArrayList(); + tickNumber = -10; + int currSmeltSize = 0; + for (int i = 3; i < contain.inventorySlots.inventorySlots.size(); i++) { + Slot slot = contain.inventorySlots.inventorySlots.get(i); + if (!slot.getHasStack()) { + continue; + } + ItemStack in = slot.getStack(); + if (in == null) { + continue; + } + if (in.getItem().equals(toPutInTheFurnace.getItem())) { + int amountHere = in.stackSize; + int amountNeeded = desiredAmount - currSmeltSize; + leftClick(i); + if (amountNeeded >= amountHere) { + leftClick(0); + currSmeltSize += amountHere; + leftClick(i); + } else { + for (int j = 0; j < amountNeeded; j++) { + rightClick(0); + } + leftClick(i); + break; + } + } + } + for (int i = 3; i < contain.inventorySlots.inventorySlots.size(); i++) { + Slot slot = contain.inventorySlots.inventorySlots.get(i); + if (!slot.getHasStack()) { + continue; + } + ItemStack in = slot.getStack(); + if (in == null) { + continue; + } + if (in.getItem().equals(bestFuel)) { + int currentSize = currFuelSize; + int amountHere = in.stackSize; + int amountNeeded = fuelAmt - currentSize; + leftClick(i); + if (amountNeeded >= amountHere) { + leftClick(1); + currFuelSize += amountHere; + leftClick(i); + } else { + for (int j = 0; j < amountNeeded; j++) { + rightClick(1); + } + leftClick(i); + Out.gui("done with fuel", Out.Mode.Debug); + break; + } + } + } + return true; + } + public void leftClick(int slot) { + if (!plan.isEmpty()) { + int[] last = plan.get(plan.size() - 1); + if (last[0] == slot && last[1] == 0 && last[2] == 0) { + plan.remove(plan.size() - 1); + return; + } + } + plan.add(new int[]{slot, 0, 0}); + } + public void rightClick(int slot) { + plan.add(new int[]{slot, 1, 0}); + } + public void shiftClick(int slot) { + plan.add(new int[]{slot, 0, 1}); + } + private static boolean isEmpty(GuiFurnace contain, int id) { + Slot slot = contain.inventorySlots.inventorySlots.get(id); + if (!slot.getHasStack()) { + return true; + } + return slot.getStack() == null; + } + private static int currentSize1(GuiFurnace contain, int id, Item item) { + Slot slot = contain.inventorySlots.inventorySlots.get(id); + if (!slot.getHasStack()) { + return 0; + } + ItemStack in = slot.getStack(); + if (in == null) { + return 0; + } + if (!in.getItem().equals(item)) { + return -1; + } + return in.stackSize; + } + private static ItemStack recipe(ItemStack desired) { + for (Entry recipe : getRecipes().entrySet()) { + ItemStack input = recipe.getKey(); + ItemStack output = recipe.getValue(); + if (output.getItem().equals(desired.getItem())) { + int desiredQuantity = desired.stackSize; + int outputQuantity = output.stackSize; + int totalQuantity = (int) Math.ceil(((double) desiredQuantity) / (outputQuantity)); + int inputQuantity = input.stackSize * totalQuantity; + Out.log("Recipe from " + input + " to " + output + " " + desiredQuantity + " " + outputQuantity + " " + totalQuantity + " " + inputQuantity); + if (inputQuantity > 64) { + throw new IllegalStateException("lol"); + } + return new ItemStack(input.getItem(), inputQuantity, input.getMetadata()); + } + } + return null; + } + @Override + protected void onCancel() { + inProgress.clear(); + furnacesInUse.clear(); + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } + + private static class wrapper {//so that people don't try to directly reference recipess + private static Map recipes = null; + public static Map getRecipes() { + if (recipes == null) { + recipes = FurnaceRecipes.instance().getSmeltingList(); + } + return recipes; + } + } + public static Map getRecipes() { + return wrapper.getRecipes(); + } +} diff --git a/mining/MickeyMine.java b/mining/MickeyMine.java new file mode 100644 index 00000000..a2e7e3a4 --- /dev/null +++ b/mining/MickeyMine.java @@ -0,0 +1,464 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.mining; + +import java.util.ArrayList; +import baritone.ui.LookManager; +import baritone.util.Memory; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.pathfinding.actions.Action; +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.goals.GoalBlock; +import baritone.pathfinding.goals.GoalComposite; +import baritone.pathfinding.goals.GoalTwoBlocks; +import baritone.pathfinding.goals.GoalYLevel; +import baritone.inventory.CraftingTask; +import baritone.util.Manager; +import baritone.util.ManagerTick; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.chunk.Chunk; + +/** + * + * @author galdara + */ +public class MickeyMine extends ManagerTick { + public static final int Y_DIAMOND = 13; + public static final int Y_IRON = 36; + public static int yLevel = Y_DIAMOND; + static ArrayList goalBlocks = null; + static boolean isGoingToMine = false; + static boolean isMining = false; + public static boolean tempDisable = false; + static EnumFacing miningFacing = EnumFacing.EAST; + static ArrayList diamondChunks = new ArrayList(); + static ArrayList hasBeenMined = new ArrayList(); + static ArrayList needsToBeMined = new ArrayList(); + static ArrayList priorityNeedsToBeMined = new ArrayList(); + static ArrayList chunkHasDiamonds = new ArrayList(); + static BlockPos branchPosition = null; + static final String[] ores = {"diamond", "iron", "coal", "gold", "emerald"}; + static final boolean[] enabled = {true, true, false, true, true}; + static boolean mightNeedToGoBackToPath = false; + public static void notifyFullness(String item, boolean isFull) { + if (item.equals("stone")) { + return; + } + boolean up = false; + for (int i = 0; i < ores.length; i++) { + if (ores[i].endsWith(item)) { + if (enabled[i] == isFull) { + Out.gui((isFull ? "is full" : "not full") + " of " + item + " so therefore " + ores[i], Out.Mode.Minimal); + enabled[i] = !isFull; + up = true; + } + } + } + if (up) { + calculateGoal(); + } + } + public static void toggleOre(String ore) { + String lower = ore.toLowerCase(); + if (lower.trim().length() == 0) { + for (int i = 0; i < ores.length; i++) { + Out.gui(ores[i] + ": " + enabled[i], Out.Mode.Minimal); + } + return; + } + boolean m = false; + for (int i = 0; i < ores.length; i++) { + if (!ores[i].contains(lower)) { + Out.gui(ores[i] + ": " + enabled[i], Out.Mode.Minimal); + continue; + } + m = true; + enabled[i] = !enabled[i]; + Out.gui(ores[i] + ": " + enabled[i] + " (I toggled this one just now)", Out.Mode.Minimal); + } + if (m) { + goalBlocks = new ArrayList(); + calculateGoal(); + } + } + public static void calculateGoal() { + goalBlocks = new ArrayList(); + for (int i = 0; i < ores.length; i++) { + if (!enabled[i]) { + continue; + } + String oreName = "minecraft:" + ores[i] + "_ore"; + Block block = Block.getBlockFromName(oreName); + if (block == null) { + Out.gui(oreName + " doesn't exist bb", Out.Mode.Minimal); + throw new NullPointerException(oreName + " doesn't exist bb"); + } + goalBlocks.add(block); + } + } + public static void doMine() { + if (goalBlocks == null) { + calculateGoal(); + } + MovementManager.clearMovement(); + Out.log("Goal blocks: " + goalBlocks); + Out.log("priority: " + priorityNeedsToBeMined); + Out.log("needs to be mined: " + needsToBeMined); + updateBlocksMined(); + if (priorityNeedsToBeMined.isEmpty() && needsToBeMined.isEmpty()) { + doBranchMine(); + } else if (priorityNeedsToBeMined.isEmpty()) { + doNormalMine(); + } + if (ticksSinceBlockMined > 200) { + Out.gui("Mickey mine stops, its been like 10 seconds and nothing has happened", Out.Mode.Debug); + Manager.getManager(MickeyMine.class).cancel(); + } + } + public static boolean torch() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + CraftingTask.ensureCraftingDesired(Item.getByNameOrId("minecraft:torch"), 32); + for (int i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + continue; + } + if (item.getItem().equals(Item.getByNameOrId("minecraft:torch"))) { + p.inventory.currentItem = i; + return true; + } + } + return false; + } + public static void doBranchMine() { + if (branchPosition == null) { + BlockPos player = Minecraft.getMinecraft().player.getPosition0(); + branchPosition = new BlockPos(player.getX(), yLevel, player.getZ()); + } + if (!Memory.blockLoaded(branchPosition)) {//if this starts before chunks load, this thing just goes on forever + branchPosition = null; + return; + } + if (!branchPosition.equals(Minecraft.getMinecraft().player.getPosition0())) { + Out.gui("Should be at branch position " + branchPosition + " " + Minecraft.getMinecraft().player.getPosition0(), Out.Mode.Debug); + mightNeedToGoBackToPath = true; + } else if (torch()) { + if (LookManager.lookAtBlock(branchPosition.down(), true)) { + Minecraft.getMinecraft().rightClickMouse(); + } else { + return; + } + } + int i; + int l = 5; + for (i = 0; i < l || diamondChunks.contains(tupleFromBlockPos(branchPosition.offset(miningFacing, i))); i++) { + addNormalBlock(branchPosition.offset(miningFacing, i).up(), true); + addNormalBlock(branchPosition.offset(miningFacing, i), true); + Out.log("branche" + i); + if (i >= l) { + Out.gui("Not mining " + branchPosition.offset(miningFacing, i) + " because it's in known diamond chunk " + tupleFromBlockPos(branchPosition.offset(miningFacing, i)), Out.Mode.Debug); + } + } + i--; + Out.gui("Branch distance " + i, Out.Mode.Debug); + BlockPos futureBranchPosition = branchPosition.offset(miningFacing, i); + if (futureBranchPosition.getY() != yLevel) { + onCancel1(); + return; + } + Out.log("player reach: " + Minecraft.getMinecraft().playerController.getBlockReachDistance()); + for (int j = 1; j <= Math.ceil(Minecraft.getMinecraft().playerController.getBlockReachDistance()); j++) { + addNormalBlock(futureBranchPosition.offset(miningFacing.rotateY(), j).up(), false); + } + for (int j = 1; j <= Math.ceil(Minecraft.getMinecraft().playerController.getBlockReachDistance()); j++) { + addNormalBlock(futureBranchPosition.offset(miningFacing.rotateYCCW(), j).up(), false); + } + branchPosition = futureBranchPosition; + } + public static void doPriorityMine() { + Goal[] toComposite = new Goal[priorityNeedsToBeMined.size()]; + for (int i = 0; i < toComposite.length; i++) { + toComposite[i] = new GoalTwoBlocks(priorityNeedsToBeMined.get(i)); + } + Baritone.goal = new GoalComposite(toComposite); + if (Baritone.currentPath == null && !Baritone.isPathFinding()) { + Baritone.findPathInNewThread(Minecraft.getMinecraft().player.getPosition0(), false); + } else { + addNearby(); + } + } + public static void addNearby() { + BlockPos playerFeet = Minecraft.getMinecraft().player.getPosition0(); + int searchDist = 4;//why four? idk + for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) { + for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) { + for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) { + BlockPos pos = new BlockPos(x, y, z); + if (isGoalBlock(pos)) { + if (LookManager.couldIReach(pos)) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught + addPriorityBlock(pos); + } + } + } + } + } + } + public static void doNormalMine() { + if (mightNeedToGoBackToPath) { + Baritone.goal = new GoalBlock(branchPosition); + if (Baritone.currentPath == null && !Baritone.isPathFinding()) { + Baritone.findPathInNewThread(Minecraft.getMinecraft().player.getPosition0(), false); + Out.gui("Pathing back to branch", Out.Mode.Standard); + } + if (Minecraft.getMinecraft().player.getPosition0().equals(branchPosition)) { + mightNeedToGoBackToPath = false; + Out.gui("I'm back", Out.Mode.Debug); + } + return; + } + addNearby(); + BlockPos toMine = needsToBeMined.get(0); + if (LookManager.lookAtBlock(toMine, true)) { + if (Action.avoidBreaking(toMine)) { + miningFacing = miningFacing.rotateY(); + Out.gui("Since I need to avoid breaking " + toMine + ", I'm rotating to " + miningFacing, Out.Mode.Debug); + needsToBeMined.clear(); + //.priorityNeedsToBeMined.clear(); + } else { + Baritone.switchToBestTool(); + MovementManager.isLeftClick = true; + Out.log("Looking"); + if (Minecraft.getMinecraft().player.getPosition0().equals(branchPosition)) { + Out.log("IN position"); + if (Baritone.whatAreYouLookingAt() == null) { + Out.log("Can't see, going"); + MovementManager.forward = true; + } + } else { + Out.log("Going to position"); + if (!Action.canWalkOn(Minecraft.getMinecraft().player.getPosition0().offset(Minecraft.getMinecraft().player.getHorizontalFacing()).down())) { + Out.gui("About to fall off", Out.Mode.Debug); + mightNeedToGoBackToPath = true; + return; + } + MovementManager.moveTowardsBlock(branchPosition, false); + if (Minecraft.getMinecraft().player.getPosition0().getY() != branchPosition.getY()) { + Out.gui("wrong Y coordinate", Out.Mode.Debug); + mightNeedToGoBackToPath = true; + } + } + } + } + } + static double ticksSinceBlockMined = 0; + public static void updateBlocksMined() { + if (Baritone.currentPath == null) { + ticksSinceBlockMined++; + } else { + ticksSinceBlockMined += 0.1; + } + ArrayList shouldBeRemoved = new ArrayList(); + for (BlockPos isMined : needsToBeMined) { + Block block = net.minecraft.client.Minecraft.getMinecraft().world.getBlockState(isMined).getBlock(); + if (isGoalBlock(isMined) || block.equals(Block.getBlockById(0)) || block.equals(Block.getBlockFromName("minecraft:torch")) || block.equals(Blocks.bedrock)) { + hasBeenMined.add(isMined); + shouldBeRemoved.add(isMined); + updateBlocks(isMined); + ticksSinceBlockMined = 0; + } + } + for (BlockPos needsRemoval : shouldBeRemoved) { + needsToBeMined.remove(needsRemoval); + } + } + public static void updatePriorityBlocksMined() { + boolean wasEmpty = priorityNeedsToBeMined.isEmpty(); + ArrayList shouldBeRemoved = new ArrayList(); + for (BlockPos isMined : priorityNeedsToBeMined) { + Block block = net.minecraft.client.Minecraft.getMinecraft().world.getBlockState(isMined).getBlock(); + if (block.equals(Block.getBlockById(0)) || block.equals(Block.getBlockFromName("minecraft:torch")) || block.equals(Blocks.bedrock)) { + hasBeenMined.add(isMined); + shouldBeRemoved.add(isMined); + updateBlocks(isMined); + ticksSinceBlockMined = 0; + } + } + for (BlockPos needsRemoval : shouldBeRemoved) { + priorityNeedsToBeMined.remove(needsRemoval); + } + if (priorityNeedsToBeMined.isEmpty() && !wasEmpty) { + mightNeedToGoBackToPath = true; + if (!chunkHasDiamonds.isEmpty()) { + for (IntegerTuple shouldAdd : chunkHasDiamonds) { + if (!diamondChunks.contains(shouldAdd)) { + diamondChunks.add(shouldAdd); + } + } + chunkHasDiamonds.clear(); + } + } + } + public static void updateBlocks(BlockPos blockPos) { + for (int i = 0; i < 4; i++) { + Out.log(blockPos.offset(miningFacing)); + } + addPriorityBlock(blockPos); + addPriorityBlock(blockPos.north()); + addPriorityBlock(blockPos.south()); + addPriorityBlock(blockPos.east()); + addPriorityBlock(blockPos.west()); + addPriorityBlock(blockPos.up()); + addPriorityBlock(blockPos.down()); + } + public static boolean addNormalBlock(BlockPos blockPos, boolean mainBranch) { + if (!needsToBeMined.contains(blockPos)) { + if (Action.avoidBreaking(blockPos) && mainBranch) {//who gives a crap if a side branch will hit lava? lol + Out.gui("Uh oh, lava nearby", Out.Mode.Debug); + miningFacing = miningFacing.rotateY(); + return false; + } + needsToBeMined.add(blockPos); + return true; + } + return false; + } + public static boolean addPriorityBlock(BlockPos blockPos) { + if (!priorityNeedsToBeMined.contains(blockPos) && isGoalBlock(blockPos)) { + if (Action.avoidBreaking(blockPos)) { + Out.gui("Can't break " + Minecraft.getMinecraft().world.getBlockState(blockPos).getBlock() + " at " + blockPos + " because it's near lava", Out.Mode.Debug); + return false; + } + priorityNeedsToBeMined.add(blockPos); + if (Block.getBlockFromName("minecraft:diamond_ore").equals(Minecraft.getMinecraft().world.getBlockState(blockPos).getBlock())) { + chunkHasDiamonds.add(tupleFromBlockPos(blockPos)); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + BlockPos oth = new BlockPos(blockPos.getX() + x, blockPos.getY() + y, blockPos.getZ() + z); + if (!Action.avoidBreaking(oth) && !priorityNeedsToBeMined.contains(oth)) { + priorityNeedsToBeMined.add(oth); + } + } + } + } + } + return true; + } + return false; + } + public static boolean isGoalBlock(BlockPos blockPos) { + return isGoalBlock(Minecraft.getMinecraft().world.getBlockState(blockPos).getBlock()); + } + public static boolean isGoalBlock(Block block) { + return goalBlocks.contains(block); + } + public static boolean isNull(Object object) { + try { + object.toString(); + return false; + } catch (NullPointerException ex) { + return true; + } + } + public static IntegerTuple tupleFromChunk(Chunk chunk) { + return new IntegerTuple(chunk.xPosition, chunk.zPosition); + } + public static IntegerTuple tupleFromBlockPos(BlockPos blockPos) { + return tupleFromChunk(Minecraft.getMinecraft().world.getChunkFromBlockCoords(blockPos)); + } + @Override + protected boolean onTick0() { + if (tempDisable) { + return false; + } + Out.log("mickey" + isGoingToMine + " " + isMining); + if (!isGoingToMine && !isMining) { + Baritone.goal = new GoalYLevel(yLevel); + if (Baritone.currentPath == null && !Baritone.isPathFinding()) { + Baritone.findPathInNewThread(Minecraft.getMinecraft().player.getPosition0(), true); + isGoingToMine = true; + } + } + if (isGoingToMine && Minecraft.getMinecraft().player.getPosition0().getY() == yLevel) { + isGoingToMine = false; + isMining = true; + } + updatePriorityBlocksMined(); + if (isMining) { + doMine(); + } + if (!priorityNeedsToBeMined.isEmpty()) { + doPriorityMine(); + } + Out.log("mickey done"); + return false; + } + @Override + protected void onCancel() { + onCancel1(); + } + private static void onCancel1() { + isGoingToMine = false; + isMining = false; + needsToBeMined.clear(); + priorityNeedsToBeMined.clear(); + branchPosition = null; + mightNeedToGoBackToPath = false; + ticksSinceBlockMined = 0; + } + @Override + protected void onStart() { + } + @Override + protected void onTickPre() { + tempDisable = false; + } + + public static class IntegerTuple {//why not use the normal net.minecraft.util.Tuple? Because it doesn't implement equals or hashCode + private final int a; + private final int b; + public IntegerTuple(int a, int b) { + this.a = a; + this.b = b; + } + @Override + public String toString() { + return a + "," + b; + } + @Override + public int hashCode() { + int hash = 3; + hash = 73 * hash + this.a; + hash = 73 * hash + this.b; + return hash; + } + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final IntegerTuple other = (IntegerTuple) obj; + if (this.a != other.a) { + return false; + } + return this.b == other.b; + } + } +} diff --git a/movement/Combat.java b/movement/Combat.java new file mode 100644 index 00000000..68e60838 --- /dev/null +++ b/movement/Combat.java @@ -0,0 +1,261 @@ + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.movement; + +import baritone.ui.LookManager; +import java.util.ArrayList; +import java.util.Comparator; +import baritone.Baritone; +import static baritone.Baritone.findPathInNewThread; +import static baritone.Baritone.goal; +import static baritone.Baritone.isAir; +import static baritone.Baritone.whatEntityAreYouLookingAt; +import baritone.pathfinding.goals.GoalRunAway; +import baritone.pathfinding.goals.GoalTwoBlocks; +import baritone.util.ManagerTick; +import baritone.util.Out; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.EntityEnderman; +import net.minecraft.entity.monster.EntityMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * this entire class is sketchy i don't even know + * + * @author leijurv + */ +public class Combat extends ManagerTick { + public static boolean mobHunting = false; + public static boolean mobKilling = false; + public static boolean playerHunt = false; + public static Entity target = null; + public static boolean wasTargetSetByMobHunt = false; + @Override + public boolean onTick0() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + World theWorld = Minecraft.getMinecraft().world; + BlockPos playerFeet = new BlockPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + boolean healthOkToHunt = Minecraft.getMinecraft().player.getHealth() >= 12 || (target != null && target instanceof EntityPlayer); + ArrayList killAura = new ArrayList(); + for (Entity entity : theWorld.loadedEntityList) { + if (entity.isEntityAlive() && !(entity instanceof EntityEnderman)) { + if ((mobKilling && entity instanceof EntityMob) || ((playerHunt && (entity instanceof EntityPlayer) && !(entity.getName().equals(thePlayer.getName())) && !couldBeInCreative((EntityPlayer) entity)))) { + if (distFromMe(entity) < 5) { + killAura.add(entity); + } + } + } + } + killAura.sort(new Comparator() { + @Override + public int compare(Entity o1, Entity o2) { + return new Double(distFromMe(o1)).compareTo(distFromMe(o2)); + } + }); + if (!killAura.isEmpty()) { + Entity entity = killAura.get(0); + AxisAlignedBB lol = entity.getEntityBoundingBox(); + switchtosword(); + Out.log("looking"); + LookManager.lookAtCoords((lol.minX + lol.maxX) / 2, (lol.minY + lol.maxY) / 2, (lol.minZ + lol.maxZ) / 2, true); + if (entity.equals(Baritone.whatEntityAreYouLookingAt())) { + MovementManager.isLeftClick = true; + if (Baritone.tickNumber % 10 < 3) { + MovementManager.isLeftClick = false; + } + tickPath = false; + Out.log("Doing it"); + } + } + ArrayList huntMobs = new ArrayList(); + for (Entity entity : theWorld.loadedEntityList) { + if (entity.isEntityAlive() && distFromMe(entity) < 30 && !(entity instanceof EntityEnderman)) { + if (!playerHunt && (entity instanceof EntityMob) && entity.posY > thePlayer.posY - 6) { + huntMobs.add(entity); + } + if ((playerHunt && (entity instanceof EntityPlayer) && !(entity.getName().equals(thePlayer.getName())) && !couldBeInCreative((EntityPlayer) entity))) { + huntMobs.add(entity); + } + } + } + huntMobs.sort(new Comparator() { + @Override + public int compare(Entity o1, Entity o2) { + return new Double(distFromMe(o1)).compareTo(distFromMe(o2)); + } + }); + if (mobHunting && (target == null || wasTargetSetByMobHunt)) { + if (!huntMobs.isEmpty()) { + Entity entity = huntMobs.get(0); + if (!entity.equals(target)) { + if (!(!(entity instanceof EntityPlayer) && (target instanceof EntityPlayer) && playerHunt)) {//if playerhunt is true, dont overwrite a player target with a non player target + Out.gui("Mobhunting=true. Killing " + entity, Out.Mode.Minimal); + Baritone.currentPath = null; + target = entity; + wasTargetSetByMobHunt = true; + } + } + } + } + if (!healthOkToHunt && target != null && wasTargetSetByMobHunt && mobHunting) { + if (Baritone.currentPath != null) { + if (!(Baritone.currentPath.goal instanceof GoalRunAway)) { + Out.gui("Health too low, cancelling hunt", Out.Mode.Minimal); + Baritone.currentPath = null; + } + } + MovementManager.clearMovement(); + BlockPos[] away = new BlockPos[Math.min(5, huntMobs.size())]; + for (int i = 0; i < away.length; i++) { + away[i] = new BlockPos(huntMobs.get(i).posX, huntMobs.get(i).posY, huntMobs.get(i).posZ); + } + if (away.length != 0) { + Baritone.goal = new GoalRunAway(35, away); + if (Baritone.currentPath == null || (!Baritone.isThereAnythingInProgress && Baritone.tickNumber % 4 == 0)) { + Out.gui("Running away", Out.Mode.Minimal); + Baritone.findPathInNewThread(playerFeet, false); + } + } + } + if (target != null && target.isDead) { + Out.gui(target + " is dead", Out.Mode.Standard); + target = null; + Baritone.currentPath = null; + MovementManager.clearMovement(); + } + if (target != null && healthOkToHunt) { + BlockPos targetPos = new BlockPos(target.posX, target.posY, target.posZ); + Baritone.goal = new GoalTwoBlocks(targetPos); + if (Baritone.currentPath != null) { + double movementSince = dist(targetPos, Baritone.currentPath.end); + if (movementSince > 4 && !Baritone.isThereAnythingInProgress) { + Out.gui("They moved too much, " + movementSince + " blocks. recalculating", Out.Mode.Standard); + Baritone.findPathInNewThread(playerFeet, true);//this will overwrite currentPath + } + } + double dist = distFromMe(target); + boolean actuallyLookingAt = target.equals(Baritone.whatEntityAreYouLookingAt()); + //Out.gui(dist + " " + actuallyLookingAt, Out.Mode.Debug); + if (dist > 4 && Baritone.currentPath == null) { + Baritone.findPathInNewThread(playerFeet, true); + } + if (dist <= 4) { + AxisAlignedBB lol = target.getEntityBoundingBox(); + switchtosword(); + boolean direction = LookManager.lookAtCoords((lol.minX + lol.maxX) / 2, (lol.minY + lol.maxY) / 2, (lol.minZ + lol.maxZ) / 2, true); + if (direction && !actuallyLookingAt) { + Baritone.findPathInNewThread(playerFeet, false); + } + } + if (actuallyLookingAt) { + MovementManager.isLeftClick = true; + if (Baritone.tickNumber % 10 < 3) { + MovementManager.isLeftClick = false; + } + tickPath = false; + } + } + return false; + } + public static double distFromMe(Entity a) { + EntityPlayerSP player = Minecraft.getMinecraft().player; + double diffX = player.posX - a.posX; + double diffY = player.posY - a.posY; + double diffZ = player.posZ - a.posZ; + return Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); + } + public static boolean couldBeInCreative(EntityPlayer player) { + if (player.capabilities.isCreativeMode || player.capabilities.allowFlying || player.capabilities.isFlying) { + return true; + } + BlockPos inFeet = new BlockPos(player.posX, player.posY, player.posZ); + BlockPos standingOn = inFeet.down(); + return isAir(standingOn) && isAir(standingOn.north()) && isAir(standingOn.south()) && isAir(standingOn.east()) && isAir(standingOn.west()) && isAir(standingOn.north().west()) && isAir(standingOn.north().east()) && isAir(standingOn.south().west()) && isAir(standingOn.south().east()); + } + public static double dist(BlockPos a, BlockPos b) { + int diffX = a.getX() - b.getX(); + int diffY = a.getY() - b.getY(); + int diffZ = a.getZ() - b.getZ(); + return Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ); + } + public static void switchtosword() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + float bestDamage = 0; + for (byte i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + item = new ItemStack(Item.getByNameOrId("minecraft:apple")); + } + if (item.getItem() instanceof ItemSword) { + float damage = ((ItemSword) (item.getItem())).getDamageVsEntity(); + if (damage > bestDamage) { + p.inventory.currentItem = i; + bestDamage = damage; + } + } + if (item.getItem() instanceof ItemAxe) { + if (bestDamage == 0) { + p.inventory.currentItem = i; + } + } + } + } + public static String killCommand(String name) {//TODO make this use Memory.playerLocationMemory + BlockPos playerFeet = Minecraft.getMinecraft().player.getPosition0(); + if (name.length() > 2) { + for (EntityPlayer pl : Minecraft.getMinecraft().world.playerEntities) { + String blah = pl.getName().trim().toLowerCase(); + if (!blah.equals(Minecraft.getMinecraft().player.getName().trim().toLowerCase())) { + Out.gui("Considering " + blah, Out.Mode.Debug); + if (Combat.couldBeInCreative(pl)) { + Out.gui("No, creative", Out.Mode.Minimal); + continue; + } + if (blah.contains(name) || name.contains(blah)) { + Combat.target = pl; + Combat.wasTargetSetByMobHunt = false; + BlockPos pos = new BlockPos(Combat.target.posX, Combat.target.posY, Combat.target.posZ); + goal = new GoalTwoBlocks(pos); + findPathInNewThread(playerFeet, false); + return "Killing " + pl; + } + } + } + } + Entity w = whatEntityAreYouLookingAt(); + if (w != null) { + Combat.target = w; + BlockPos pos = new BlockPos(Combat.target.posX, Combat.target.posY, Combat.target.posZ); + goal = new GoalTwoBlocks(pos); + Combat.wasTargetSetByMobHunt = false; + findPathInNewThread(playerFeet, false); + return "Killing " + w; + } + return "Couldn't find " + name; + } + @Override + protected void onCancel() { + target = null; + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } +} diff --git a/movement/MovementManager.java b/movement/MovementManager.java new file mode 100644 index 00000000..767675e8 --- /dev/null +++ b/movement/MovementManager.java @@ -0,0 +1,202 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.movement; + +import baritone.ui.LookManager; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockVine; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class MovementManager { + public static boolean forward = false; + public static int leftPressTime = 0; + public static boolean isRightClick = false; + public static int rightPressTime = 0; + public static boolean right = false; + public static boolean left = false; + public static boolean jumping = false; + public static boolean sneak = false; + public static boolean isLeftClick = false; + public static boolean backward = false; + /** + * calls moveTowardsCoords on the center of this block + * + * @param p + * @return am I moving, or am I still rotating + */ + public static boolean moveTowardsBlock(BlockPos p) { + return moveTowardsBlock(p, true); + } + public static boolean moveTowardsBlock(BlockPos p, boolean rotate) { + Block b = Minecraft.getMinecraft().world.getBlockState(p).getBlock(); + double xDiff = (b.getBlockBoundsMinX() + b.getBlockBoundsMaxX()) / 2; + double yolo = (b.getBlockBoundsMinY() + b.getBlockBoundsMaxY()) / 2; + double zDiff = (b.getBlockBoundsMinZ() + b.getBlockBoundsMaxZ()) / 2; + if (b instanceof BlockLadder || b instanceof BlockVine) { + xDiff = 0.5; + yolo = 0.5; + zDiff = 0.5; + } + double x = p.getX() + xDiff; + double y = p.getY() + yolo; + double z = p.getZ() + zDiff; + return moveTowardsCoords(x, y, z, rotate); + } + /** + * Clears movement, but nothing else. Includes jumping and sneaking, but not + * left clicking. + */ + public static void clearMovement() { + jumping = false; + forward = false; + left = false; + right = false; + backward = false; + sneak = false; + isRightClick = false; + //rightPressTime = 0; + isLeftClick = false; + //leftPressTime = 0; + } + /** + * Do not question the logic. Called by Minecraft.java + * + * @return + */ + public static boolean rightIsPressed() { + if (rightPressTime <= 0) { + return false; + } else { + --rightPressTime; + return true; + } + } + /** + * Called by our code + */ + public static void letGoOfLeftClick() { + leftPressTime = 0; + isLeftClick = false; + } + /** + * Do not question the logic. Called by Minecraft.java + * + * @return + */ + public static boolean getLeftIsPressed() { + return isLeftClick && leftPressTime >= -2; + } + /** + * Do not question the logic. Called by Minecraft.java + * + * @return + */ + public static boolean leftIsPressed() { + if (leftPressTime <= 0) { + return false; + } else { + --leftPressTime; + return true; + } + } + /** + * Do not question the logic. Called by Minecraft.java + * + * @return + */ + public static boolean getRightIsPressed() { + return isRightClick && rightPressTime >= -2; + } + public static boolean moveTowardsCoords(double x, double y, double z) { + return moveTowardsCoords(x, y, z, true); + } + /** + * Move towards coordinates, not necesarily forwards. e.g. if coordinates + * are closest to being directly behind us, go backwards. This minimizes + * time spent waiting for rotating + * + * @param x + * @param y + * @param z + * @param doRotate + * @return true if we are moving, false if we are still rotating. we will + * rotate until within ANGLE_THRESHOLD (currently 7°) of moving in correct + * direction + */ + public static boolean moveTowardsCoords(double x, double y, double z, boolean doRotate) { + boolean rotate = doRotate; + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + float currentYaw = thePlayer.rotationYaw; + float yaw = (float) (Math.atan2(thePlayer.posX - x, -thePlayer.posZ + z) * 180 / Math.PI); + float diff = yaw - currentYaw; + if (diff < 0) { + diff += 360; + } + float distanceToForward = Math.min(Math.abs(diff - 0), Math.abs(diff - 360)) % 360; + float distanceToForwardRight = Math.abs(diff - 45) % 360; + float distanceToRight = Math.abs(diff - 90) % 360; + float distanceToBackwardRight = Math.abs(diff - 135) % 360; + float distanceToBackward = Math.abs(diff - 180) % 360; + float distanceToBackwardLeft = Math.abs(diff - 225) % 360; + float distanceToLeft = Math.abs(diff - 270) % 360; + float distanceToForwardLeft = Math.abs(diff - 315) % 360; + float tmp = Math.round(diff / 45) * 45; + if (tmp > 359) { + tmp -= 360; + } + if (rotate) { + if (LookManager.lookingYaw()) {//if something else has set the yaw, just move anyway + rotate = false; + } + LookManager.setDesiredYaw(yaw - tmp); + } + double t = rotate ? LookManager.ANGLE_THRESHOLD : 23; + if (distanceToForward < t || distanceToForward > 360 - t) { + forward = true; + return true; + } + if (distanceToForwardLeft < t || distanceToForwardLeft > 360 - t) { + forward = true; + left = true; + return true; + } + if (distanceToForwardRight < t || distanceToForwardRight > 360 - t) { + forward = true; + right = true; + return true; + } + if (distanceToBackward < t || distanceToBackward > 360 - t) { + backward = true; + return true; + } + if (distanceToBackwardLeft < t || distanceToBackwardLeft > 360 - t) { + backward = true; + left = true; + return true; + } + if (distanceToBackwardRight < t || distanceToBackwardRight > 360 - t) { + backward = true; + right = true; + return true; + } + if (distanceToLeft < t || distanceToLeft > 360 - t) { + left = true; + return true; + } + if (distanceToRight < t || distanceToRight > 360 - t) { + right = true; + return true; + } + return false; + } +} diff --git a/movement/Parkour.java b/movement/Parkour.java new file mode 100644 index 00000000..29c6143d --- /dev/null +++ b/movement/Parkour.java @@ -0,0 +1,72 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.movement; + +import baritone.pathfinding.actions.Action; +import baritone.util.Manager; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author leijurv + */ +public class Parkour extends Manager { + public static boolean preemptivejump() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + BlockPos playerFeet = thePlayer.getPosition0(); + EnumFacing dir = thePlayer.getHorizontalFacing(); + for (int height = 0; height < 3; height++) { + BlockPos bp = playerFeet.offset(dir, 1).up(height); + if (!Minecraft.getMinecraft().world.getBlockState(bp).getBlock().equals(Block.getBlockById(0))) { + return Action.canWalkOn(playerFeet.offset(dir, 1)); + } + } + for (int height = 0; height < 3; height++) { + BlockPos bp = playerFeet.offset(dir, 2).up(height); + if (!Minecraft.getMinecraft().world.getBlockState(bp).getBlock().equals(Block.getBlockById(0))) { + return Action.canWalkOn(playerFeet.offset(dir, 2)); + } + } + return Action.canWalkOn(playerFeet.offset(dir, 3)); + } + public static void parkour() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + BlockPos playerFeet = thePlayer.getPosition0(); + BlockPos down = playerFeet.down(); + BlockPos prev = down.offset(thePlayer.getHorizontalFacing().getOpposite()); + boolean onAir = Minecraft.getMinecraft().world.getBlockState(down).getBlock().equals(Block.getBlockById(0)); + boolean jumpAnyway = preemptivejump(); + if (onAir || jumpAnyway) { + if ((thePlayer.isSprinting() && !Minecraft.getMinecraft().world.getBlockState(prev).getBlock().equals(Block.getBlockById(0))) || !Minecraft.getMinecraft().world.getBlockState(playerFeet.offset(thePlayer.getHorizontalFacing())).getBlock().equals(Block.getBlockById(0))) { + double distX = Math.abs(thePlayer.posX - (prev.getX() + 0.5)); + distX *= Math.abs(prev.getX() - down.getX()); + double distZ = Math.abs(thePlayer.posZ - (prev.getZ() + 0.5)); + distZ *= Math.abs(prev.getZ() - down.getZ()); + double dist = distX + distZ; + thePlayer.rotationYaw = Math.round(thePlayer.rotationYaw / 90) * 90; + if (dist > 0.7) { + MovementManager.jumping = true; + Out.gui("Parkour jumping!!!", Out.Mode.Standard); + } + } + } + } + @Override + protected void onTick() { + parkour(); + } + @Override + protected void onCancel() { + } + @Override + protected void onStart() { + } +} diff --git a/pathfinding/Node.java b/pathfinding/Node.java new file mode 100644 index 00000000..331234da --- /dev/null +++ b/pathfinding/Node.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding; + +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.actions.Action; +import java.util.Objects; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class Node { + final BlockPos pos; + double cost; + Node previous; + final Goal goal; + final double estimatedCostToGoal; + Action previousAction; + boolean isOpen; + Node nextOpen; + public Node(BlockPos pos, Goal goal) { + this.pos = pos; + this.previous = null; + this.cost = Short.MAX_VALUE; + this.goal = goal; + this.estimatedCostToGoal = goal.heuristic(pos); + this.previousAction = null; + this.isOpen = false; + } + @Override + public int hashCode() {//this is some OG code right here + int hash = 3241; + hash = 3457689 * hash + this.pos.getX(); + hash = 8734625 * hash + this.pos.getY(); + hash = 2873465 * hash + this.pos.getZ(); + hash = 3241543 * hash + Objects.hashCode(this.goal); + return hash; + } + @Override + public boolean equals(Object obj) {//autogenerated by netbeans. that's why it looks disgusting. + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Node other = (Node) obj; + if (!Objects.equals(this.pos, other.pos)) { + return false; + } + return Objects.equals(this.goal, other.goal); + } +} diff --git a/pathfinding/Path.java b/pathfinding/Path.java new file mode 100644 index 00000000..0cc4fcf4 --- /dev/null +++ b/pathfinding/Path.java @@ -0,0 +1,269 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding; + +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.actions.ActionBridge; +import baritone.pathfinding.actions.Action; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.pathfinding.actions.ActionPlaceOrBreak; +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class Path { + public final BlockPos start; + public final BlockPos end; + public final Goal goal; + /** + * The blocks on the path. Guaranteed that path.get(0) equals start and + * path.get(path.size()-1) equals end + */ + public final ArrayList path; + final ArrayList actions; + /** + * note that this ISN'T the number of nodes in this path, it's actually the + * number of nodes used to calculate this path. this is here for idk why + * + */ + public final int numNodes; + Path(Node start, Node end, Goal goal, int numNodes) { + this.numNodes = numNodes; + this.start = start.pos; + this.end = end.pos; + this.goal = goal; + this.path = new ArrayList(); + this.actions = new ArrayList(); + Node current = end; + while (!current.equals(start)) {//assemble the path + path.add(0, current.pos); + actions.add(0, current.previousAction); + current = current.previous; + } + path.add(0, start.pos); + /*Out.log("Final path: " + path); + Out.log("Final actions: " + actions); + for (int i = 0; i < path.size() - 1; i++) {//print it all out + int oldX = path.get(i).getX(); + int oldY = path.get(i).getY(); + int oldZ = path.get(i).getZ(); + int newX = path.get(i + 1).getX(); + int newY = path.get(i + 1).getY(); + int newZ = path.get(i + 1).getZ(); + int xDiff = newX - oldX; + int yDiff = newY - oldY; + int zDiff = newZ - oldZ; + Out.log(actions.get(i) + ": " + xDiff + "," + yDiff + "," + zDiff);//print it all out + }*/ + } + /** + * We don't really use this any more + */ + public void showPathInStone() { + IBlockState[] originalStates = new IBlockState[path.size()]; + for (int i = 0; i < path.size(); i++) { + originalStates[i] = Minecraft.getMinecraft().world.getBlockState(path.get(i)); + Minecraft.getMinecraft().world.setBlockState(path.get(i), Block.getBlockById(1).getDefaultState()); + try { + Thread.sleep(250); + } catch (InterruptedException ex) { + Logger.getLogger(Path.class.getName()).log(Level.SEVERE, null, ex); + } + } + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + Logger.getLogger(Path.class.getName()).log(Level.SEVERE, null, ex); + } + for (int i = 0; i < path.size(); i++) { + Minecraft.getMinecraft().world.setBlockState(path.get(i), originalStates[i]); + } + } + /** + * Where are we in the path? This is an index in the actions list + */ + int pathPosition = 0; + public double howFarAmIFromThePath(double x, double y, double z) { + double best = -1; + for (BlockPos pos : path) { + double dist = distance(x, y, z, pos); + if (dist < best || best == -1) { + best = dist; + } + } + return best; + } + public void calculatePathPosition() { + BlockPos playerFeet = Minecraft.getMinecraft().player.getPosition0(); + for (int i = 0; i < path.size(); i++) { + if (playerFeet.equals(path.get(i))) { + pathPosition = i; + } + } + } + public static double distance(double x, double y, double z, BlockPos pos) { + double xdiff = x - (pos.getX() + 0.5D); + double ydiff = y - (pos.getY() + 0.5D); + double zdiff = z - (pos.getZ() + 0.5D); + return Math.sqrt(xdiff * xdiff + ydiff * ydiff + zdiff * zdiff); + } + /** + * How many ticks have I been more than MAX_DISTANCE_FROM_PATH away from the + * path + */ + int ticksAway = 0; + /** + * How far away from the path can I get and still be okay + */ + static final double MAX_DISTANCE_FROM_PATH = 2; + /** + * How many ticks can I be more than MAX_DISTANCE_FROM_PATH before we + * consider it a failure + */ + static final int MAX_TICKS_AWAY = 20 * 10; + /** + * How many ticks have elapsed on this action + */ + int ticksOnCurrent = 0; + /** + * Did I fail, either by being too far away for too long, or by having an + * action take too long + */ + public boolean failed = false; + public boolean tick() { + if (pathPosition >= path.size()) { + Baritone.clearPath();//stop bugging me, I'm done + return true; + } + BlockPos whereShouldIBe = path.get(pathPosition); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + BlockPos whereAmI = thePlayer.getPosition0(); + if (pathPosition == path.size() - 1) { + Out.log("On last path position"); + Baritone.clearPath(); + return true; + } + if (!whereShouldIBe.equals(whereAmI)) { + Out.log("Should be at " + whereShouldIBe + " actually am at " + whereAmI); + if (!Blocks.air.equals(Minecraft.getMinecraft().world.getBlockState(thePlayer.getPosition0().down()))) {//do not skip if standing on air, because our position isn't stable to skip + for (int i = 0; i < pathPosition - 2 && i < path.size(); i++) {//this happens for example when you lag out and get teleported back a couple blocks + if (whereAmI.equals(path.get(i))) { + Out.gui("Skipping back " + (pathPosition - i) + " steps, to " + i, Out.Mode.Debug); + pathPosition = Math.max(i - 1, 0); + return false; + } + } + for (int i = pathPosition + 2; i < path.size(); i++) {//dont check pathPosition+1 + if (whereAmI.equals(path.get(i))) { + Out.gui("Skipping forward " + (i - pathPosition) + " steps, to " + i, Out.Mode.Debug); + pathPosition = i - 1; + return false; + } + } + } + } + double distanceFromPath = howFarAmIFromThePath(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + if (distanceFromPath > MAX_DISTANCE_FROM_PATH) { + ticksAway++; + Out.log("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + distanceFromPath + ". Threshold: " + MAX_DISTANCE_FROM_PATH); + if (ticksAway > MAX_TICKS_AWAY) { + Out.gui("Too far away from path for too long, cancelling path", Out.Mode.Standard); + Out.log("Too many ticks"); + pathPosition = path.size() + 3; + failed = true; + return true; + } + } else { + ticksAway = 0; + } + Out.log(actions.get(pathPosition)); + if (pathPosition < actions.size() - 1) {//if there are two ActionBridges in a row and they are at right angles, walk diagonally. This makes it so you walk at 45 degrees along a zigzag path instead of doing inefficient zigging and zagging + if ((actions.get(pathPosition) instanceof ActionBridge) && (actions.get(pathPosition + 1) instanceof ActionBridge)) { + ActionBridge curr = (ActionBridge) actions.get(pathPosition); + ActionBridge next = (ActionBridge) actions.get(pathPosition + 1); + if (curr.dx() != next.dx() || curr.dz() != next.dz()) {//two actions are not parallel, so this is a right angle + if (curr.amIGood() && next.amIGood()) {//nothing in the way + BlockPos cornerToCut1 = new BlockPos(next.to.getX() - next.from.getX() + curr.from.getX(), next.to.getY(), next.to.getZ() - next.from.getZ() + curr.from.getZ()); + BlockPos cornerToCut2 = cornerToCut1.up(); + //Block corner1 = Minecraft.getMinecraft().world.getBlockState(cornerToCut1).getBlock(); + //Block corner2 = Minecraft.getMinecraft().world.getBlockState(cornerToCut2).getBlock(); + //Out.gui("Cutting conner " + cornerToCut1 + " " + corner1, Out.Mode.Debug); + if (!Action.avoidWalkingInto(cornerToCut1) && !Action.avoidWalkingInto(cornerToCut2)) { + double x = (next.from.getX() + next.to.getX() + 1.0D) * 0.5D; + double z = (next.from.getZ() + next.to.getZ() + 1.0D) * 0.5D; + MovementManager.clearMovement(); + if (!MovementManager.forward && curr.oneInTen != null && curr.oneInTen) { + MovementManager.clearMovement(); + MovementManager.forward = LookManager.lookAtCoords(x, 0, z, false); + } else { + MovementManager.moveTowardsCoords(x, 0, z); + } + if (MovementManager.forward && !MovementManager.backward) { + thePlayer.setSprinting(true); + } + return false; + } + } + } + } + } + MovementManager.clearMovement(); + Action action = actions.get(pathPosition); + if (action.calculateCost0(new ToolSet()) >= Action.COST_INF) { + Out.gui("Something has changed in the world and this action has become impossible. Cancelling.", Out.Mode.Standard); + pathPosition = path.size() + 3; + failed = true; + return true; + } + if (action.tick()) { + Out.log("Action done, next path"); + pathPosition++; + ticksOnCurrent = 0; + } else { + ticksOnCurrent++; + if (ticksOnCurrent > action.cost(null) + 100) { + Out.gui("This action has taken too long (" + ticksOnCurrent + " ticks, expected " + action.cost(null) + "). Cancelling.", Out.Mode.Standard); + pathPosition = path.size() + 3; + failed = true; + return true; + } + } + return false; + } + public HashSet toMine() { + HashSet tm = new HashSet<>(); + for (int i = pathPosition; i < actions.size(); i++) { + if (actions.get(i) instanceof ActionPlaceOrBreak) { + tm.addAll(((ActionPlaceOrBreak) actions.get(i)).toMine()); + } + } + return tm; + } + public HashSet toPlace() { + HashSet tp = new HashSet<>(); + for (int i = pathPosition; i < actions.size(); i++) { + if (actions.get(i) instanceof ActionPlaceOrBreak) { + tp.addAll(((ActionPlaceOrBreak) actions.get(i)).toPlace()); + } + } + return tp; + } +} diff --git a/pathfinding/PathFinder.java b/pathfinding/PathFinder.java new file mode 100644 index 00000000..234adb43 --- /dev/null +++ b/pathfinding/PathFinder.java @@ -0,0 +1,268 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding; + +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.actions.ActionDescendTwo; +import baritone.pathfinding.actions.ActionBridge; +import baritone.pathfinding.actions.ActionClimb; +import baritone.pathfinding.actions.Action; +import baritone.pathfinding.actions.ActionDescend; +import baritone.pathfinding.actions.ActionFall; +import baritone.pathfinding.actions.ActionPillar; +import java.util.HashMap; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.Baritone; +import baritone.pathfinding.actions.ActionDescendThree; +import baritone.pathfinding.actions.ActionWalkDiagonal; +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.chunk.EmptyChunk; + +/** + * + * @author leijurv + */ +public class PathFinder { + final BlockPos start; + final Goal goal; + final HashMap map; + public PathFinder(BlockPos start, Goal goal) { + this.start = start; + this.goal = goal; + this.map = new HashMap(); + } + static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; + public static PathFinder currentlyRunning = null; + Node[] bestSoFar; + Node startNode; + Node mostRecentConsidered; + public Path getTempSolution() { + if (startNode == null || bestSoFar[0] == null) { + return null; + } + return new Path(startNode, bestSoFar[0], goal, 0); + } + public Path getMostRecentNodeConsidered() { + return mostRecentConsidered == null ? null : new Path(startNode, mostRecentConsidered, goal, 0); + } + /** + * Do the actual path calculation. The returned path might not actually go + * to goal, but it will get as close as I could get + * + * @return + */ + public Path calculatePath() { + //a lot of these vars are local. that's because if someone tries to call this from multiple threads, they won't interfere (much) + startNode = getNodeAtPosition(start); + startNode.cost = 0; + bestSoFar = new Node[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) + double[] bestHeuristicSoFar = new double[COEFFICIENTS.length]; + for (int i = 0; i < bestHeuristicSoFar.length; i++) { + bestHeuristicSoFar[i] = Double.MAX_VALUE; + } + OpenSet openSet = new OpenSet(); + startNode.isOpen = true; + openSet.insert(startNode); + currentlyRunning = this; + long startTime = System.currentTimeMillis(); + long timeoutTime = startTime + (Baritone.slowPath ? 40000 : 4000); + long lastPrintout = 0; + int numNodes = 0; + ToolSet ts = new ToolSet(); + int numEmptyChunk = 0; + while (openSet.first != null && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) { + if (Baritone.slowPath) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + Logger.getLogger(PathFinder.class.getName()).log(Level.SEVERE, null, ex); + } + } + Node currentNode = openSet.removeLowest(); + mostRecentConsidered = currentNode; + currentNode.isOpen = false; + currentNode.nextOpen = null; + BlockPos currentNodePos = currentNode.pos; + numNodes++; + if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second + Out.log("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far"); + lastPrintout = System.currentTimeMillis(); + } + if (goal.isInGoal(currentNodePos)) { + currentlyRunning = null; + return new Path(startNode, currentNode, goal, numNodes); + } + //long constructStart = System.nanoTime(); + Action[] possibleActions = getConnectedPositions(currentNodePos);//actions that we could take that start at myPos, in random order + shuffle(possibleActions); + //long constructEnd = System.nanoTime(); + //System.out.println(constructEnd - constructStart); + for (Action actionToGetToNeighbor : possibleActions) { + //long costStart = System.nanoTime(); + double actionCost = actionToGetToNeighbor.cost(ts); + //long costEnd = System.nanoTime(); + //System.out.println(actionToGetToNeighbor.getClass() + "" + (costEnd - costStart)); + if (actionCost >= Action.COST_INF) { + continue; + } + if (Minecraft.getMinecraft().world.getChunkFromBlockCoords(actionToGetToNeighbor.to) instanceof EmptyChunk) { + numEmptyChunk++; + continue; + } + Node neighbor = getNodeAtPosition(actionToGetToNeighbor.to); + double tentativeCost = currentNode.cost + actionCost; + if (tentativeCost < neighbor.cost) { + neighbor.previous = currentNode; + neighbor.previousAction = actionToGetToNeighbor; + neighbor.cost = tentativeCost; + if (!neighbor.isOpen) { + openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there + neighbor.isOpen = true; + } + for (int i = 0; i < bestSoFar.length; i++) { + double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; + if (heuristic < bestHeuristicSoFar[i]) { + bestHeuristicSoFar[i] = heuristic; + bestSoFar[i] = neighbor; + } + } + } + } + } + double bestDist = 0; + for (int i = 0; i < bestSoFar.length; i++) { + if (bestSoFar[i] == null) { + continue; + } + double dist = distFromStart(bestSoFar[i]); + if (dist > bestDist) { + bestDist = dist; + } + if (dist > MIN_DIST_PATH) { + Out.gui("A* cost coefficient " + COEFFICIENTS[i], Out.Mode.Debug); + if (COEFFICIENTS[i] >= 3) { + Out.gui("Warning: cost coefficient is greater than three! Probably means that", Out.Mode.Debug); + Out.gui("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)", Out.Mode.Debug); + Out.gui("But I'm going to do it anyway, because yolo", Out.Mode.Debug); + } + Out.gui("Path goes for " + dist + " blocks", Out.Mode.Debug); + currentlyRunning = null; + return new Path(startNode, bestSoFar[i], goal, numNodes); + } + } + Out.gui("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks =(", Out.Mode.Debug); + Out.gui("No path found =(", Out.Mode.Standard); + currentlyRunning = null; + return null; + } + private double distFromStart(Node n) { + int xDiff = n.pos.getX() - start.getX(); + int yDiff = n.pos.getY() - start.getY(); + int zDiff = n.pos.getZ() - start.getZ(); + return Math.sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff); + } + private final double MIN_DIST_PATH = 5; + private Node getNodeAtPosition(BlockPos pos) { + Node alr = map.get(pos); + if (alr == null) { + Node node = new Node(pos, goal); + map.put(pos, node); + return node; + } + return alr; + } + private static Action[] getConnectedPositions(BlockPos pos) { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + Action[] actions = new Action[26]; + actions[0] = new ActionPillar(pos); + actions[1] = new ActionBridge(pos, new BlockPos(x + 1, y, z)); + actions[2] = new ActionBridge(pos, new BlockPos(x - 1, y, z)); + actions[3] = new ActionBridge(pos, new BlockPos(x, y, z + 1)); + actions[4] = new ActionBridge(pos, new BlockPos(x, y, z - 1)); + actions[5] = new ActionClimb(pos, new BlockPos(x + 1, y + 1, z)); + actions[6] = new ActionClimb(pos, new BlockPos(x - 1, y + 1, z)); + actions[7] = new ActionClimb(pos, new BlockPos(x, y + 1, z + 1)); + actions[8] = new ActionClimb(pos, new BlockPos(x, y + 1, z - 1)); + actions[9] = new ActionDescend(pos, new BlockPos(x, y - 1, z - 1)); + actions[10] = new ActionDescend(pos, new BlockPos(x, y - 1, z + 1)); + actions[11] = new ActionDescend(pos, new BlockPos(x - 1, y - 1, z)); + actions[12] = new ActionDescend(pos, new BlockPos(x + 1, y - 1, z)); + actions[13] = new ActionFall(pos); + actions[14] = new ActionDescendTwo(pos, new BlockPos(x, y - 2, z - 1)); + actions[15] = new ActionDescendTwo(pos, new BlockPos(x, y - 2, z + 1)); + actions[16] = new ActionDescendTwo(pos, new BlockPos(x - 1, y - 2, z)); + actions[17] = new ActionDescendTwo(pos, new BlockPos(x + 1, y - 2, z)); + actions[18] = new ActionDescendThree(pos, new BlockPos(x, y - 3, z - 1)); + actions[19] = new ActionDescendThree(pos, new BlockPos(x, y - 3, z + 1)); + actions[20] = new ActionDescendThree(pos, new BlockPos(x - 1, y - 3, z)); + actions[21] = new ActionDescendThree(pos, new BlockPos(x + 1, y - 3, z)); + actions[22] = new ActionWalkDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST); + actions[23] = new ActionWalkDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST); + actions[24] = new ActionWalkDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST); + actions[25] = new ActionWalkDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST); + return actions; + } + private final Random random = new Random(); + private void shuffle(Action[] list) { + int len = list.length; + for (int i = 0; i < len; i++) { + int j = random.nextInt(len); + Action e = list[j]; + list[j] = list[i]; + list[i] = e; + } + } + + /** + * My own implementation of a singly linked list + */ + private static class OpenSet { + Node first = null; + public Node removeLowest() { + if (first == null) { + return null; + } + Node current = first.nextOpen; + if (current == null) { + Node n = first; + first = null; + return n; + } + Node previous = first; + double bestValue = first.estimatedCostToGoal + first.cost; + Node bestNode = first; + Node beforeBest = null; + while (current != null) { + double comp = current.estimatedCostToGoal + current.cost; + if (comp < bestValue) { + bestValue = comp; + bestNode = current; + beforeBest = previous; + } + previous = current; + current = current.nextOpen; + } + if (beforeBest == null) { + first = first.nextOpen; + return bestNode; + } + beforeBest.nextOpen = bestNode.nextOpen; + return bestNode; + } + public void insert(Node node) { + node.nextOpen = first; + first = node; + } + } +} diff --git a/pathfinding/actions/Action.java b/pathfinding/actions/Action.java new file mode 100644 index 00000000..0da0e5cb --- /dev/null +++ b/pathfinding/actions/Action.java @@ -0,0 +1,211 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockCactus; +import net.minecraft.block.BlockFire; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockLilyPad; +import net.minecraft.block.BlockLiquid; +import net.minecraft.block.BlockVine; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public abstract class Action { + + //These costs are measured roughly in ticks btw + public static final double WALK_ONE_BLOCK_COST = 20 / 4.317; + public static final double WALK_ONE_IN_WATER_COST = 20 / 2.2; + public static final double JUMP_ONE_BLOCK_COST = 5.72854;//see below calculation for fall. 1.25 blocks + public static final double LADDER_UP_ONE_COST = 20 / 2.35; + public static final double LADDER_DOWN_ONE_COST = 20 / 3; + public static final double SNEAK_ONE_BLOCK_COST = 20 / 1.3; + public static final double SPRINT_ONE_BLOCK_COST = 20 / 5.612; + /** + * Doesn't include walking forwards, just the falling + * + * Based on a sketchy formula from minecraftwiki + * + * d(t) = 3.92 × (99 - 49.50×(0.98^t+1) - t) + * + * Solved in mathematica + */ + public static final double FALL_ONE_BLOCK_COST = 5.11354; + public static final double FALL_TWO_BLOCK_COST = 7.28283; + public static final double FALL_THREE_BLOCK_COST = 8.96862; + /** + * It doesn't actually take ten ticks to place a block, this cost is so high + * because we want to generally conserve blocks which might be limited + */ + public static final double PLACE_ONE_BLOCK_COST = 20; + /** + * Add this to the cost of breaking any block. The cost of breaking any + * block is calculated as the number of ticks that block takes to break with + * the tools you have. You add this because there's always a little overhead + * (e.g. looking at the block) + */ + public static final double BREAK_ONE_BLOCK_ADD = 4; + public static final double COST_INF = 1000000; + public final BlockPos from; + public final BlockPos to; + private Double cost; + public boolean finished = false; + + protected Action(BlockPos from, BlockPos to) { + this.from = from; + this.to = to; + this.cost = null; + } + + /** + * Get the cost. It's cached + * + * @param ts + * @return + */ + public double cost(ToolSet ts) { + if (cost == null) { + cost = calculateCost0(ts == null ? new ToolSet() : ts); + } + if (cost < 1) { + Out.log("Bad cost " + this + " " + cost); + } + return cost; + } + + public double calculateCost0(ToolSet ts) { + if (!(this instanceof ActionPillar) && !(this instanceof ActionBridge) && !(this instanceof ActionFall)) { + Block fromDown = Minecraft.getMinecraft().world.getBlockState(from.down()).getBlock(); + if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) { + return COST_INF; + } + } + return calculateCost(ts); + } + + protected abstract double calculateCost(ToolSet ts); + static Block waterFlowing = Block.getBlockById(8); + static Block waterStill = Block.getBlockById(9); + static Block lavaFlowing = Block.getBlockById(10); + static Block lavaStill = Block.getBlockById(11); + + /** + * Is this block water? Includes both still and flowing + * + * @param b + * @return + */ + public static boolean isWater(Block b) { + return waterFlowing.equals(b) || waterStill.equals(b); + } + + public static boolean isWater(BlockPos bp) { + return isWater(Minecraft.getMinecraft().world.getBlockState(bp).getBlock()); + } + + public static boolean isLiquid(Block b) { + return b instanceof BlockLiquid; + //return b != null && (waterFlowing.equals(b) || waterStill.equals(b) || lavaFlowing.equals(b) || lavaStill.equals(b)); + } + + public static boolean isFlowing(BlockPos pos, IBlockState state) { + Block b = state.getBlock(); + Material m = b.getMaterial(state); + if (b instanceof BlockLiquid) { + throw new UnsupportedOperationException("TODO"); + //return BlockLiquid.getFlow(Minecraft.getMinecraft().world, pos, state) != -1000.0D; + } + return false; + } + + public static boolean isLava(Block b) { + return lavaFlowing.equals(b) || lavaStill.equals(b); + } + + public static boolean isLiquid(BlockPos p) { + return isLiquid(Minecraft.getMinecraft().world.getBlockState(p).getBlock()); + } + + public static boolean avoidBreaking(BlockPos pos) { + Block b = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + Block below = Minecraft.getMinecraft().world.getBlockState(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ())).getBlock(); + return Block.getBlockFromName("minecraft:ice").equals(b)//ice becomes water, and water can mess up the path + || isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side + || isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ())) + || isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ())) + || isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1)) + || isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1)) + || (!(b instanceof BlockLilyPad && isWater(below)) && isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid + } + + /** + * Can I walk through this block? e.g. air, saplings, torches, etc + * + * @param pos + * @return + */ + public static boolean canWalkThrough(BlockPos pos) { + IBlockState state = Minecraft.getMinecraft().world.getBlockState(pos); + Block block = state.getBlock(); + if (block instanceof BlockLilyPad || block instanceof BlockFire) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire + return false; + } + if (isFlowing(pos, state)) { + return false;//don't walk through flowing liquids + } + if (isLiquid(pos.up())) { + return false;//you could drown + } + return block.isPassable(Minecraft.getMinecraft().world, pos); + } + + public static boolean avoidWalkingInto(BlockPos pos) { + Block block = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + if (isLava(block)) { + return true; + } + if (block instanceof BlockCactus) { + return true; + } + return block instanceof BlockFire; + } + + /** + * Can I walk on this block without anything weird happening like me falling + * through? Includes water because we know that we automatically jump on + * lava + * + * @param pos + * @return + */ + public static boolean canWalkOn(BlockPos pos) { + IBlockState state = Minecraft.getMinecraft().world.getBlockState(pos); + Block block = state.getBlock(); + if (block instanceof BlockLadder || block instanceof BlockVine) { + return true; + } + if (isWater(block)) { + return isWater(pos.up());//you can only walk on water if there is water above it + } + return block.isBlockNormalCube(state) && !isLava(block); + } + + /** + * Tick this action + * + * @return is it done + */ + public abstract boolean tick(); +} diff --git a/pathfinding/actions/ActionBridge.java b/pathfinding/actions/ActionBridge.java new file mode 100644 index 00000000..d3f31d00 --- /dev/null +++ b/pathfinding/actions/ActionBridge.java @@ -0,0 +1,178 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import java.util.Objects; +import java.util.Random; +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockVine; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author leijurv + */ +public class ActionBridge extends ActionPlaceOrBreak { + BlockPos[] against = new BlockPos[3]; + public ActionBridge(BlockPos from, BlockPos to) { + super(from, to, new BlockPos[]{to.up(), to}, new BlockPos[]{to.down()}); + int i = 0; + if (!to.north().equals(from)) { + against[i] = to.north().down(); + i++; + } + if (!to.south().equals(from)) { + against[i] = to.south().down(); + i++; + } + if (!to.east().equals(from)) { + against[i] = to.east().down(); + i++; + } + if (!to.west().equals(from)) { + against[i] = to.west().down(); + i++; + } + //note: do NOT add ability to place against .down().down() + } + @Override + protected double calculateCost(ToolSet ts) { + double WC = isWater(blocksToBreak[0]) || isWater(blocksToBreak[1]) ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST; + if (canWalkOn(positionsToPlace[0])) {//this is a walk, not a bridge + if (canWalkThrough(positionsToBreak[0]) && canWalkThrough(positionsToBreak[1])) { + return WC; + } + //double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]); + //double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]); + //Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")"); + return WC + getTotalHardnessOfBlocksToBreak(ts); + } else {//this is a bridge, so we need to place a block + //return 1000000; + Block f = Minecraft.getMinecraft().world.getBlockState(from.down()).getBlock(); + if (f instanceof BlockLadder || f instanceof BlockVine) { + return COST_INF; + } + if (blocksToPlace[0].equals(Block.getBlockById(0)) || (!isWater(blocksToPlace[0]) && blocksToPlace[0].isReplaceable(Minecraft.getMinecraft().world, positionsToPlace[0]))) { + for (BlockPos against1 : against) { + if (Minecraft.getMinecraft().world.getBlockState(against1).getBlock().isBlockNormalCube()) { + return WC + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(ts); + } + } + WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking + return WC + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(ts); + } + return COST_INF; + //Out.log("Can't walk on " + Minecraft.getMinecraft().world.getBlockState(positionsToPlace[0]).getBlock()); + } + } + boolean wasTheBridgeBlockAlwaysThere = true;//did we have to place a bridge block or was it always there + public Boolean oneInTen = null;//a one in ten chance + public boolean amIGood() { + return canWalkThrough(positionsToBreak[0]) && canWalkThrough(positionsToBreak[1]) && canWalkOn(positionsToPlace[0]); + } + public int dx() { + return to.getX() - from.getX(); + } + public int dz() { + return to.getZ() - from.getZ(); + } + @Override + protected boolean tick0() { + if (oneInTen == null) { + oneInTen = new Random().nextInt(10) == 0; + } + Block fd = Minecraft.getMinecraft().world.getBlockState(from.down()).getBlock(); + boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine; + boolean isTheBridgeBlockThere = canWalkOn(positionsToPlace[0]) || ladder; + //Out.log("is block there: " + isTheBridgeBlockThere + " block " + Minecraft.getMinecraft().world.getBlockState(positionsToPlace[0]).getBlock()); + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + BlockPos whereAmI = new BlockPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + if (whereAmI.getY() != to.getY() && !ladder) { + Out.log("Wrong Y coordinate"); + if (whereAmI.getY() < to.getY()) { + MovementManager.jumping = true; + } + return false; + } + if (isTheBridgeBlockThere) {//either the bridge block was there the whole time or we just placed it + if (oneInTen && wasTheBridgeBlockAlwaysThere) { + //basically one in every ten blocks we walk forwards normally without sneaking and placing, rotate to look forwards. + //this way we tend towards looking forwards + MovementManager.forward = LookManager.lookAtBlock(to, false); + } else { + MovementManager.moveTowardsBlock(to); + } + if (wasTheBridgeBlockAlwaysThere) { + if (MovementManager.forward && !MovementManager.backward) { + thePlayer.setSprinting(true); + } + } + if (whereAmI.equals(to)) {//if we are there + Out.log("Done walking to " + to); + return true;//and we are done + } + Out.log("Trying to get to " + to + " currently at " + whereAmI); + return false;//not there yet + } else { + wasTheBridgeBlockAlwaysThere = false; + for (BlockPos against1 : against) { + if (Minecraft.getMinecraft().world.getBlockState(against1).getBlock().isBlockNormalCube()) { + if (!switchtothrowaway(true)) {//get ready to place a throwaway block + return false; + } + MovementManager.sneak = true; + double faceX = (to.getX() + against1.getX() + 1.0D) * 0.5D; + double faceY = (to.getY() + against1.getY()) * 0.5D; + double faceZ = (to.getZ() + against1.getZ() + 1.0D) * 0.5D; + LookManager.lookAtCoords(faceX, faceY, faceZ, true); + EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit; + if (Objects.equals(Baritone.whatAreYouLookingAt(), against1) && Minecraft.getMinecraft().player.isSneaking()) { + if (Baritone.whatAreYouLookingAt().offset(side).equals(positionsToPlace[0])) { + Minecraft.getMinecraft().rightClickMouse(); + } else { + Out.gui("Wrong. " + side + " " + Baritone.whatAreYouLookingAt().offset(side) + " " + positionsToPlace[0], Out.Mode.Debug); + } + } + Out.log("Trying to look at " + against1 + ", actually looking at" + Baritone.whatAreYouLookingAt()); + return false; + } + } + MovementManager.sneak = true; + if (whereAmI.equals(to)) { + //if we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of + //Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI); + if (!switchtothrowaway(true)) {//get ready to place a throwaway block + return false; + } + double faceX = (to.getX() + from.getX() + 1.0D) * 0.5D; + double faceY = (to.getY() + from.getY() - 1.0D) * 0.5D; + double faceZ = (to.getZ() + from.getZ() + 1.0D) * 0.5D; + //faceX,faceY,faceZ is the middle of the face between from and to + BlockPos goalLook = from.down();//this is the block we were just standing on, and the one we want to place against + MovementManager.backward = LookManager.lookAtCoords(faceX, faceY, faceZ, true);//if we are in the block, then we are off the edge of the previous looking backward, so we should be moving backward + if (Objects.equals(Baritone.whatAreYouLookingAt(), goalLook)) { + Minecraft.getMinecraft().rightClickMouse();//wait to right click until we are able to place + return false; + } + Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt()); + return false; + } else { + Out.log("Not there yet m9"); + MovementManager.moveTowardsBlock(to);//move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block + return false; + } + } + } +} diff --git a/pathfinding/actions/ActionClimb.java b/pathfinding/actions/ActionClimb.java new file mode 100644 index 00000000..7f658599 --- /dev/null +++ b/pathfinding/actions/ActionClimb.java @@ -0,0 +1,107 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import java.util.Objects; +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.block.BlockFalling; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author leijurv + */ +public class ActionClimb extends ActionPlaceOrBreak { + BlockPos[] against = new BlockPos[3]; + public ActionClimb(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{end, start.up(2), end.up()}, new BlockPos[]{end.down()}); + BlockPos placementLocation = positionsToPlace[0];//end.down() + int i = 0; + if (!placementLocation.north().equals(from)) { + against[i] = placementLocation.north(); + i++; + } + if (!placementLocation.south().equals(from)) { + against[i] = placementLocation.south(); + i++; + } + if (!placementLocation.east().equals(from)) { + against[i] = placementLocation.east(); + i++; + } + if (!placementLocation.west().equals(from)) { + against[i] = placementLocation.west(); + i++; + } + //TODO: add ability to place against .down() as well as the cardinal directions + //useful for when you are starting a staircase without anything to place against + } + @Override + protected double calculateCost(ToolSet ts) { + if (!canWalkOn(positionsToPlace[0])) { + if (!Baritone.isAir(positionsToPlace[0]) && !isWater(positionsToPlace[0])) { + return COST_INF; + } + for (BlockPos against1 : against) { + if (Minecraft.getMinecraft().world.getBlockState(against1).getBlock().isBlockNormalCube()) { + return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(ts); + } + } + return COST_INF; + } + if (Minecraft.getMinecraft().world.getBlockState(from.up(3)).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us + return COST_INF; + } + return WALK_ONE_BLOCK_COST / 2 + Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST / 2) + getTotalHardnessOfBlocksToBreak(ts);//we walk half the block to get to the edge, then we walk the other half while simultaneously jumping (math.max because of how it's in parallel) + } + int ticksWithoutPlacement = 0; + @Override + protected boolean tick0() {//basically just hold down W and space until we are where we want to be + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + if (!canWalkOn(positionsToPlace[0])) { + for (int i = 0; i < against.length; i++) { + if (Minecraft.getMinecraft().world.getBlockState(against[i]).getBlock().isBlockNormalCube()) { + if (!switchtothrowaway(true)) {//get ready to place a throwaway block + return false; + } + double faceX = (to.getX() + against[i].getX() + 1.0D) * 0.5D; + double faceY = (to.getY() + against[i].getY()) * 0.5D; + double faceZ = (to.getZ() + against[i].getZ() + 1.0D) * 0.5D; + LookManager.lookAtCoords(faceX, faceY, faceZ, true); + EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit; + if (Objects.equals(Baritone.whatAreYouLookingAt(), against[i]) && Baritone.whatAreYouLookingAt().offset(side).equals(positionsToPlace[0])) { + ticksWithoutPlacement++; + MovementManager.sneak = true; + if (Minecraft.getMinecraft().player.isSneaking()) { + Minecraft.getMinecraft().rightClickMouse(); + } + if (ticksWithoutPlacement > 20) { + MovementManager.backward = true;//we might be standing in the way, move back + } + } + Out.log("Trying to look at " + against[i] + ", actually looking at" + Baritone.whatAreYouLookingAt()); + return false; + } + } + Out.gui("This is impossible", Out.Mode.Standard); + return false; + } + double flatDistToNext = Math.abs(to.getX() - from.getX()) * Math.abs((to.getX() + 0.5D) - thePlayer.posX) + Math.abs(to.getZ() - from.getZ()) * Math.abs((to.getZ() + 0.5D) - thePlayer.posZ); + boolean pointingInCorrectDirection = MovementManager.moveTowardsBlock(to); + MovementManager.jumping = flatDistToNext < 1.2 && pointingInCorrectDirection; + //once we are pointing the right way and moving, start jumping + //this is slightly more efficient because otherwise we might start jumping before moving, and fall down without moving onto the block we want to jump onto + //also wait until we are close enough, because we might jump and hit our head on an adjacent block + return Minecraft.getMinecraft().player.getPosition0().equals(to); + } +} diff --git a/pathfinding/actions/ActionDescend.java b/pathfinding/actions/ActionDescend.java new file mode 100644 index 00000000..d56d04e6 --- /dev/null +++ b/pathfinding/actions/ActionDescend.java @@ -0,0 +1,40 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.movement.MovementManager; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockVine; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class ActionDescend extends ActionPlaceOrBreak { + public ActionDescend(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{end.up(2), end.up(), end}, new BlockPos[]{end.down()}); + } + @Override + protected double calculateCost(ToolSet ts) { + if (!canWalkOn(positionsToPlace[0])) { + return COST_INF; + } + Block tmp1 = Minecraft.getMinecraft().world.getBlockState(to).getBlock(); + if (tmp1 instanceof BlockLadder || tmp1 instanceof BlockVine) { + return COST_INF; + } + return WALK_ONE_BLOCK_COST * 0.8 + Math.max(FALL_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST * 0.2) + getTotalHardnessOfBlocksToBreak(ts);//we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) + } + @Override + protected boolean tick0() {//basically just hold down W until we are where we want to be + MovementManager.moveTowardsBlock(to); + return Minecraft.getMinecraft().player.getPosition0().equals(to); + } +} diff --git a/pathfinding/actions/ActionDescendThree.java b/pathfinding/actions/ActionDescendThree.java new file mode 100644 index 00000000..d0275d50 --- /dev/null +++ b/pathfinding/actions/ActionDescendThree.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.movement.MovementManager; +import baritone.util.ToolSet; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class ActionDescendThree extends ActionPlaceOrBreak { + public ActionDescendThree(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{end.up(4), end.up(3), end.up(2), end.up(), end}, new BlockPos[]{end.down()}); + } + @Override + protected double calculateCost(ToolSet ts) { + if (!canWalkOn(positionsToPlace[0])) { + return COST_INF; + } + if (getTotalHardnessOfBlocksToBreak(ts) != 0) { + return COST_INF; + } + return WALK_ONE_BLOCK_COST * 0.8 + Math.max(FALL_THREE_BLOCK_COST, WALK_ONE_BLOCK_COST * 0.2);//we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) + } + @Override + protected boolean tick0() {//basically just hold down W until we are where we want to be + MovementManager.moveTowardsBlock(to); + return Minecraft.getMinecraft().player.getPosition0().equals(to); + } +} diff --git a/pathfinding/actions/ActionDescendTwo.java b/pathfinding/actions/ActionDescendTwo.java new file mode 100644 index 00000000..52978cc3 --- /dev/null +++ b/pathfinding/actions/ActionDescendTwo.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.movement.MovementManager; +import baritone.util.ToolSet; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class ActionDescendTwo extends ActionPlaceOrBreak { + public ActionDescendTwo(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{end.up(3), end.up(2), end.up(), end}, new BlockPos[]{end.down()}); + } + @Override + protected double calculateCost(ToolSet ts) { + if (!canWalkOn(positionsToPlace[0])) { + return COST_INF; + } + if (getTotalHardnessOfBlocksToBreak(ts) != 0) { + return COST_INF; + } + return WALK_ONE_BLOCK_COST * 0.8 + Math.max(FALL_TWO_BLOCK_COST, WALK_ONE_BLOCK_COST * 0.2);//we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) + } + @Override + protected boolean tick0() {//basically just hold down W until we are where we want to be + MovementManager.moveTowardsBlock(to); + return Minecraft.getMinecraft().player.getPosition0().equals(to); + } +} diff --git a/pathfinding/actions/ActionFall.java b/pathfinding/actions/ActionFall.java new file mode 100644 index 00000000..470b6922 --- /dev/null +++ b/pathfinding/actions/ActionFall.java @@ -0,0 +1,47 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockVine; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class ActionFall extends ActionPlaceOrBreak { + public ActionFall(BlockPos start) { + super(start, start.down(), new BlockPos[]{start.down()}, new BlockPos[0]); + } + int numTicks = 0; + @Override + protected boolean tick0() { + numTicks++; + if (numTicks > 10) { + MovementManager.moveTowardsBlock(to); + } + return Minecraft.getMinecraft().player.getPosition0().equals(to); + } + @Override + protected double calculateCost(ToolSet ts) { + if (!Baritone.allowVerticalMotion || !canWalkOn(to.down())) { + return COST_INF; + } + Block td = Minecraft.getMinecraft().world.getBlockState(to).getBlock(); + boolean ladder = td instanceof BlockLadder || td instanceof BlockVine; + if (ladder) { + return LADDER_DOWN_ONE_COST; + } else { + return FALL_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(ts); + } + } +} diff --git a/pathfinding/actions/ActionPillar.java b/pathfinding/actions/ActionPillar.java new file mode 100644 index 00000000..fc4c7054 --- /dev/null +++ b/pathfinding/actions/ActionPillar.java @@ -0,0 +1,141 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.util.Out; +import baritone.util.ToolSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockFalling; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockVine; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class ActionPillar extends ActionPlaceOrBreak { + public ActionPillar(BlockPos start) { + super(start, start.up(), new BlockPos[]{start.up(2)}, new BlockPos[]{start}); + } + @Override + protected double calculateCost(ToolSet ts) { + Block fromDown = Minecraft.getMinecraft().world.getBlockState(from).getBlock(); + boolean ladder = fromDown instanceof BlockLadder || fromDown instanceof BlockVine; + if (!ladder) { + Block d = Minecraft.getMinecraft().world.getBlockState(from.down()).getBlock(); + if (d instanceof BlockLadder || d instanceof BlockVine) { + return COST_INF; + } + } + if ((!Baritone.hasThrowaway && !ladder) || !Baritone.allowVerticalMotion) { + return COST_INF; + } + if (fromDown instanceof BlockVine) { + if (getAgainst(from) == null) { + return COST_INF; + } + } + double hardness = getTotalHardnessOfBlocksToBreak(ts); + if (hardness != 0) { + Block tmp = Minecraft.getMinecraft().world.getBlockState(from.up(2)).getBlock(); + if (tmp instanceof BlockLadder || tmp instanceof BlockVine) { + hardness = 0; + } else if (!canWalkOn(from.up(3)) || canWalkThrough(from.up(3)) || Minecraft.getMinecraft().world.getBlockState(from.up(3)).getBlock() instanceof BlockFalling) {//if the block above where we want to break is not a full block, don't do it + return COST_INF; + } + } + if (isLiquid(from) || isLiquid(from.down())) {//can't pillar on water or in water + return COST_INF; + } + if (ladder) { + return LADDER_UP_ONE_COST + hardness; + } else { + return JUMP_ONE_BLOCK_COST + PLACE_ONE_BLOCK_COST + hardness; + } + } + int numTicks = 0; + public BlockPos getAgainst(BlockPos vine) { + if (Minecraft.getMinecraft().world.getBlockState(vine.north()).getBlock().isBlockNormalCube()) { + return vine.north(); + } + if (Minecraft.getMinecraft().world.getBlockState(vine.south()).getBlock().isBlockNormalCube()) { + return vine.south(); + } + if (Minecraft.getMinecraft().world.getBlockState(vine.east()).getBlock().isBlockNormalCube()) { + return vine.east(); + } + if (Minecraft.getMinecraft().world.getBlockState(vine.west()).getBlock().isBlockNormalCube()) { + return vine.west(); + } + return null; + } + @Override + protected boolean tick0() { + IBlockState fromDown = Minecraft.getMinecraft().world.getBlockState(from); + boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine; + boolean vine = fromDown.getBlock() instanceof BlockVine; + if (!ladder && !LookManager.lookAtBlock(positionsToPlace[0], true)) { + return false; + } + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + boolean blockIsThere = canWalkOn(from) || ladder; + if (ladder) { + BlockPos against = vine ? getAgainst(from) : from.offset(fromDown.getValue(BlockLadder.FACING).getOpposite()); + if (against == null) { + Out.gui("Unable to climb vines", Out.Mode.Standard); + return false; + } + if (thePlayer.getPosition0().equals(against.up()) || thePlayer.getPosition0().equals(to)) { + return true; + } + /*if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) { + Baritone.moveTowardsBlock(from); + }*/ + MovementManager.moveTowardsBlock(against); + return false; + } else { + if (!switchtothrowaway(true)) {//get ready to place a throwaway block + return false; + } + numTicks++; + MovementManager.jumping = thePlayer.posY < to.getY(); //if our Y coordinate is above our goal, stop jumping + MovementManager.sneak = true; + //otherwise jump + if (numTicks > 40) { + double diffX = thePlayer.posX - (to.getX() + 0.5); + double diffZ = thePlayer.posZ - (to.getZ() + 0.5); + double dist = Math.sqrt(diffX * diffX + diffZ * diffZ); + if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why + MovementManager.forward = true;//if it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck + } + } + if (!blockIsThere) { + Out.log("Block not there yet"); + Block fr = Minecraft.getMinecraft().world.getBlockState(from).getBlock(); + if (!(Baritone.isAir(from) || fr.isReplaceable(Minecraft.getMinecraft().world, from))) { + MovementManager.isLeftClick = true; + blockIsThere = false; + } else if (Minecraft.getMinecraft().player.isSneaking()) { + Minecraft.getMinecraft().rightClickMouse();//constantly right click + } + } + } + BlockPos whereAmI = new BlockPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + if (whereAmI.equals(to) && blockIsThere) {//if we are at our goal and the block below us is placed + Out.log("Done pillaring to " + to); + MovementManager.jumping = false;//stop jumping + return true;//we are done + } + return false; + } +} diff --git a/pathfinding/actions/ActionPlaceOrBreak.java b/pathfinding/actions/ActionPlaceOrBreak.java new file mode 100644 index 00000000..d4565bbf --- /dev/null +++ b/pathfinding/actions/ActionPlaceOrBreak.java @@ -0,0 +1,221 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import java.util.ArrayList; +import baritone.util.ToolSet; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.util.Out; +import baritone.inventory.SmeltingTask; +import net.minecraft.block.Block; +import net.minecraft.block.BlockFalling; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public abstract class ActionPlaceOrBreak extends Action { + public final BlockPos[] positionsToBreak;//the positions that need to be broken before this action can ensue + public final BlockPos[] positionsToPlace;//the positions where we need to place a block before this aciton can ensue + public final Block[] blocksToBreak;//the blocks at those positions + public final Block[] blocksToPlace; + public ActionPlaceOrBreak(BlockPos start, BlockPos end, BlockPos[] toBreak, BlockPos[] toPlace) { + super(start, end); + this.positionsToBreak = toBreak; + this.positionsToPlace = toPlace; + blocksToBreak = new Block[positionsToBreak.length]; + blocksToPlace = new Block[positionsToPlace.length]; + for (int i = 0; i < blocksToBreak.length; i++) { + blocksToBreak[i] = Minecraft.getMinecraft().world.getBlockState(positionsToBreak[i]).getBlock(); + } + for (int i = 0; i < blocksToPlace.length; i++) { + blocksToPlace[i] = Minecraft.getMinecraft().world.getBlockState(positionsToPlace[i]).getBlock(); + } + } + public double getTotalHardnessOfBlocksToBreak() {//of all the blocks we need to break before starting this action, what's the sum of how hard they are (phrasing) + ToolSet ts = new ToolSet(); + return this.getTotalHardnessOfBlocksToBreak(ts); + } + public double getTotalHardnessOfBlocksToBreak(ToolSet ts) { + double sum = 0; + HashSet toBreak = new HashSet(); + for (BlockPos positionsToBreak1 : positionsToBreak) { + toBreak.add(positionsToBreak1); + if (this instanceof ActionFall) {//if we are digging straight down, assume we have already broken the sand above us + continue; + } + BlockPos tmp = positionsToBreak1.up(); + while (canFall(tmp)) { + toBreak.add(tmp); + tmp = tmp.up(); + } + } + for (BlockPos pos : toBreak) { + sum += getHardness(ts, Minecraft.getMinecraft().world.getBlockState(pos).getBlock(), pos); + if (sum >= COST_INF) { + return COST_INF; + } + } + if (!Baritone.allowBreakOrPlace || !Baritone.hasThrowaway) { + for (int i = 0; i < blocksToPlace.length; i++) { + if (!canWalkOn(positionsToPlace[i])) { + return COST_INF; + } + } + } + return sum; + } + public static boolean canFall(BlockPos pos) { + return Minecraft.getMinecraft().world.getBlockState(pos).getBlock() instanceof BlockFalling; + } + public static double getHardness(ToolSet ts, Block block, BlockPos position) { + if (!block.equals(Block.getBlockById(0)) && !canWalkThrough(position)) { + if (avoidBreaking(position)) { + return COST_INF; + } + if (!Baritone.allowBreakOrPlace) { + return COST_INF; + } + if (SmeltingTask.avoidBreaking(position)) { + return COST_INF; + } + double m = Block.getBlockFromName("minecraft:crafting_table").equals(block) ? 10 : 1; + return m / ts.getStrVsBlock(block, position) + BREAK_ONE_BLOCK_ADD; + } + return 0; + } + @Override + public String toString() { + return this.getClass() + " place " + Arrays.asList(blocksToPlace) + " break " + Arrays.asList(blocksToBreak) + " cost " + cost(null) + " break cost " + getTotalHardnessOfBlocksToBreak(); + } + @Override + public boolean tick() { + //breaking first + for (int i = 0; i < positionsToBreak.length; i++) { + if (!canWalkThrough(positionsToBreak[i])) { + if (!Baritone.allowBreakOrPlace) { + Out.gui("BB I can't break this =(((", Out.Mode.Standard); + return false; + } + //Out.log("Breaking " + blocksToBreak[i] + " at " + positionsToBreak[i]); + boolean lookingInCorrectDirection = LookManager.lookAtBlock(positionsToBreak[i], true); + //TODO decide if when actuallyLookingAtTheBlock==true then should it still keep moving the look direction to the exact center of the block + boolean actuallyLookingAtTheBlock = positionsToBreak[i].equals(Baritone.whatAreYouLookingAt()); + if (!(lookingInCorrectDirection || actuallyLookingAtTheBlock)) { + return false; + } + /*if (!positionsToBreak[i].equals(Baritone.whatAreYouLookingAt())) {//hmmm, our crosshairs are looking at the wrong block + //TODO add a timer here, and if we are stuck looking at the wrong block for more than 1 second, do something + //(it cant take longer than twenty ticks, because the Baritone.MAX_YAW_CHANGE_PER_TICK=18, and 18*20 = 360° + Out.log("Wrong"); + return false; + }*/ + if (Baritone.whatAreYouLookingAt() != null) { + Baritone.switchtotool(Minecraft.getMinecraft().world.getBlockState(Baritone.whatAreYouLookingAt()).getBlock()); + } + MovementManager.isLeftClick = true;//hold down left click + if (canWalkThrough(positionsToBreak[i])) { + MovementManager.letGoOfLeftClick(); + Out.log("Done breaking " + blocksToBreak[i] + " at " + positionsToBreak[i]); + } + return false; + } + } + MovementManager.letGoOfLeftClick();//sometimes it keeps on left clicking so we need this here (yes it scares me too) + for (BlockPos positionsToPlace1 : positionsToPlace) { + if (!canWalkOn(positionsToPlace1)) { + if (!Baritone.allowBreakOrPlace) { + Out.gui("BB I can't place this =(((", Out.Mode.Standard); + return false; + } + //Baritone.lookAtBlock(positionsToPlace[i], true); + //Out.log("CANT DO IT. CANT WALK ON " + blocksToPlace[i] + " AT " + positionsToPlace[i]); + //one of the blocks that needs to be there isn't there + //so basically someone mined out our path from under us + // + //this doesn't really do anything, because all the cases for positionToPlace are handled in their respective action tick0s (e.g. pillar and bridge) + } + } + return tick0(); + } + //I dont want to make this static, because then it might be executed before Item gets initialized + private static List ACCEPTABLE_THROWAWAY_ITEMS = null; + private static void set() { + if (ACCEPTABLE_THROWAWAY_ITEMS != null) { + return; + } + ACCEPTABLE_THROWAWAY_ITEMS = Arrays.asList(new Item[]{Item.getByNameOrId("minecraft:dirt"), Item.getByNameOrId("minecraft:cobblestone")}); + } + public static boolean switchtothrowaway(boolean message) { + set(); + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (byte i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + item = new ItemStack(Item.getByNameOrId("minecraft:apple")); + } + if (ACCEPTABLE_THROWAWAY_ITEMS.contains(item.getItem())) { + p.inventory.currentItem = i; + return true; + } + } + if (message) { + Out.gui("bb pls get me some blocks. dirt or cobble", Out.Mode.Minimal); + } + return false; + } + public static boolean hasthrowaway() { + set(); + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + for (byte i = 0; i < 9; i++) { + ItemStack item = inv[i]; + if (inv[i] == null) { + item = new ItemStack(Item.getByNameOrId("minecraft:apple")); + } + if (ACCEPTABLE_THROWAWAY_ITEMS.contains(item.getItem())) { + return true; + } + } + return false; + } + /** + * Do the actual tick. This function can assume that all blocks in + * positionsToBreak are now walk-through-able. + * + * @return + */ + protected abstract boolean tick0(); + public ArrayList toMine() { + ArrayList result = new ArrayList<>(); + for (BlockPos positionsToBreak1 : positionsToBreak) { + if (!canWalkThrough(positionsToBreak1)) { + result.add(positionsToBreak1); + } + } + return result; + } + public ArrayList toPlace() { + ArrayList result = new ArrayList<>(); + for (BlockPos positionsToPlace1 : positionsToPlace) { + if (!canWalkOn(positionsToPlace1)) { + result.add(positionsToPlace1); + } + } + return result; + } +} diff --git a/pathfinding/actions/ActionWalkDiagonal.java b/pathfinding/actions/ActionWalkDiagonal.java new file mode 100644 index 00000000..0b3b7804 --- /dev/null +++ b/pathfinding/actions/ActionWalkDiagonal.java @@ -0,0 +1,61 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.actions; + +import java.util.Random; +import baritone.Baritone; +import baritone.movement.MovementManager; +import baritone.ui.LookManager; +import baritone.util.ToolSet; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author leijurv + */ +public class ActionWalkDiagonal extends ActionPlaceOrBreak { + public ActionWalkDiagonal(BlockPos start, EnumFacing dir1, EnumFacing dir2) { + this(start, start.offset(dir1), start.offset(dir2), dir2); + //super(start, start.offset(dir1).offset(dir2), new BlockPos[]{start.offset(dir1), start.offset(dir1).up(), start.offset(dir2), start.offset(dir2).up(), start.offset(dir1).offset(dir2), start.offset(dir1).offset(dir2).up()}, new BlockPos[]{start.offset(dir1).offset(dir2).down()}); + } + public ActionWalkDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) { + this(start, dir1.offset(drr2), dir1, dir2); + } + public ActionWalkDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) { + super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}, new BlockPos[]{end.down()}); + } + private Boolean oneInTen = null; + @Override + protected boolean tick0() { + if (oneInTen == null) { + oneInTen = new Random().nextInt(10) == 0; + } + if (oneInTen) { + MovementManager.forward = LookManager.lookAtBlock(to, false); + } else { + MovementManager.moveTowardsBlock(to); + } + if (MovementManager.forward && !MovementManager.backward) { + Minecraft.getMinecraft().player.setSprinting(true); + } + return to.equals(Minecraft.getMinecraft().player.getPosition0()); + } + @Override + protected double calculateCost(ToolSet ts) { + if (!Baritone.allowDiagonal) { + return COST_INF; + } + if (getTotalHardnessOfBlocksToBreak(ts) != 0) { + return COST_INF; + } + if (!canWalkOn(positionsToPlace[0])) { + return COST_INF; + } + return Math.sqrt(2) * (isWater(from) || isWater(to) ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST); + } +} diff --git a/pathfinding/goals/Goal.java b/pathfinding/goals/Goal.java new file mode 100644 index 00000000..c9f0f02c --- /dev/null +++ b/pathfinding/goals/Goal.java @@ -0,0 +1,31 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public interface Goal { + /** + * Does this position satisfy the goal? + * + * @param pos + * @return + */ + public boolean isInGoal(BlockPos pos); + /** + * Estimate the number of ticks it will take to get to the goal + * + * @param pos + * @return + */ + public double heuristic(BlockPos pos); + @Override + public String toString(); +} diff --git a/pathfinding/goals/GoalBlock.java b/pathfinding/goals/GoalBlock.java new file mode 100644 index 00000000..1c271a20 --- /dev/null +++ b/pathfinding/goals/GoalBlock.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import baritone.pathfinding.actions.Action; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class GoalBlock implements Goal { + final int x, y, z; + public GoalBlock() { + this(Minecraft.getMinecraft().player.playerFeet()); + } + public GoalBlock(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + public GoalBlock(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + public BlockPos pos() { + return new BlockPos(x, y, z); + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == this.x && pos.getY() == this.y && pos.getZ() == this.z; + } + static final double MIN = 20; + static final double MAX = 150; + @Override + public double heuristic(BlockPos pos) { + double xDiff = pos.getX() - this.x; + double yDiff = pos.getY() - this.y; + double zDiff = pos.getZ() - this.z; + return calculate(xDiff, yDiff, zDiff); + } + public static double calculate(double xDiff, double yDiff, double zDiff) { + double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff); + double heuristic = 0; + double baseline = (Action.PLACE_ONE_BLOCK_COST + Action.FALL_ONE_BLOCK_COST) * 32; + if (pythaDist < MAX) {//if we are more than MAX away, ignore the Y coordinate. It really doesn't matter how far away your Y coordinate is if you X coordinate is 1000 blocks away. + double multiplier = pythaDist < MIN ? 1 : 1 - (pythaDist - MIN) / (MAX - MIN); + if (yDiff < 0) {//pos.getY()-this.y<0 therefore pos.getY() blocks) { + goals = new Goal[blocks.size()]; + int i = 0; + for (BlockPos pos : blocks) { + goals[i] = new GoalBlock(pos); + i++; + } + } + public Goal[] goals() { + return goals; + } + @Override + public boolean isInGoal(BlockPos pos) { + for (Goal g : goals) { + if (g.isInGoal(pos)) { + return true; + } + } + return false; + } + @Override + public double heuristic(BlockPos pos) { + double min = Double.MAX_VALUE; + for (Goal g : goals) { + min = Math.min(min, g.heuristic(pos)); + } + return min; + } + @Override + public String toString() { + return "GoalComposite" + Arrays.toString(goals); + } +} diff --git a/pathfinding/goals/GoalGetToBlock.java b/pathfinding/goals/GoalGetToBlock.java new file mode 100644 index 00000000..2dd61305 --- /dev/null +++ b/pathfinding/goals/GoalGetToBlock.java @@ -0,0 +1,31 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; + +/** + * + * @author avecowa + */ +public class GoalGetToBlock extends GoalComposite{ + public static BlockPos goalPos; + public GoalGetToBlock(BlockPos pos) { + super(ajacentBlocks(goalPos = pos)); + } + public GoalGetToBlock(){ + this(Minecraft.getMinecraft().player.getPosition0()); + } + public static BlockPos[] ajacentBlocks(BlockPos pos){ + BlockPos[] sides = new BlockPos[6]; + for(int i = 0; i < 6; i++){ + sides[i] = pos.offset(EnumFacing.values()[i]); + } + return sides; + } +} diff --git a/pathfinding/goals/GoalRunAway.java b/pathfinding/goals/GoalRunAway.java new file mode 100644 index 00000000..bc3191c2 --- /dev/null +++ b/pathfinding/goals/GoalRunAway.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import java.util.Arrays; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class GoalRunAway implements Goal { + public final BlockPos[] from; + final double distanceSq; + public GoalRunAway(double distance, BlockPos... from) { + if (from.length == 0) { + throw new IllegalArgumentException(); + } + this.from = from; + this.distanceSq = distance * distance; + } + @Override + public boolean isInGoal(BlockPos pos) { + for (BlockPos p : from) { + int diffX = pos.getX() - p.getX(); + int diffZ = pos.getZ() - p.getZ(); + double distSq = diffX * diffX + diffZ * diffZ; + if (distSq < distanceSq) { + return false; + } + } + return true; + } + @Override + public double heuristic(BlockPos pos) {//mostly copied from GoalBlock + double min = Double.MAX_VALUE; + for (BlockPos p : from) { + double h = GoalXZ.calculate(p.getX() - pos.getX(), p.getZ() - pos.getZ()); + if (h < min) { + min = h; + } + } + return -min; + } + @Override + public String toString() { + return "GoalRunAwayFrom[" + Arrays.asList(from) + "]"; + } +} diff --git a/pathfinding/goals/GoalTwoBlocks.java b/pathfinding/goals/GoalTwoBlocks.java new file mode 100644 index 00000000..5ba5a363 --- /dev/null +++ b/pathfinding/goals/GoalTwoBlocks.java @@ -0,0 +1,42 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class GoalTwoBlocks implements Goal { + final int x, y, z; + public GoalTwoBlocks(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + public GoalTwoBlocks(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == this.x && (pos.getY() == this.y || pos.getY() == this.y - 1) && pos.getZ() == this.z; + } + @Override + public double heuristic(BlockPos pos) { + double xDiff = pos.getX() - this.x; + double yDiff = pos.getY() - this.y; + if (yDiff < 0) { + yDiff++; + } + double zDiff = pos.getZ() - this.z; + return GoalBlock.calculate(xDiff, yDiff, zDiff); + } + @Override + public String toString() { + return "GoalTwoBlocks{x=" + x + ",y=" + y + ",z=" + z + "}"; + } +} diff --git a/pathfinding/goals/GoalXZ.java b/pathfinding/goals/GoalXZ.java new file mode 100644 index 00000000..50df69f8 --- /dev/null +++ b/pathfinding/goals/GoalXZ.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import baritone.pathfinding.actions.Action; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class GoalXZ implements Goal { + final int x; + final int z; + public GoalXZ(int x, int z) { + this.x = x; + this.z = z; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == x && pos.getZ() == z; + } + @Override + public double heuristic(BlockPos pos) {//mostly copied from GoalBlock + double xDiff = pos.getX() - this.x; + double zDiff = pos.getZ() - this.z; + return calculate(xDiff, zDiff); + } + public static double calculate(double xDiff, double zDiff) { + return calculate(xDiff, zDiff, 0); + } + /* + public static double calculate(double xDiff, double zDiff) { + double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff); + return calculate(xDiff, zDiff, pythaDist); + } + public static double calculateOld(double xDiff, double zDiff, double pythaDist) { + double heuristic = 0; + heuristic += Math.abs(xDiff) * Action.WALK_ONE_BLOCK_COST * 1.1;//overestimate + heuristic += Math.abs(zDiff) * Action.WALK_ONE_BLOCK_COST * 1.1; + heuristic += pythaDist / 10 * Action.WALK_ONE_BLOCK_COST; + return heuristic; + } + */ + static final double sq = Math.sqrt(2); + public static double calculate(double xDiff, double zDiff, double pythaDist) { + double x = Math.abs(xDiff); + double z = Math.abs(zDiff); + double straight; + double diagonal; + if (x < z) { + straight = z - x; + diagonal = x; + } else { + straight = x - z; + diagonal = z; + } + diagonal *= sq; + return (diagonal + straight) * Action.WALK_ONE_BLOCK_COST; + } + @Override + public String toString() { + return "Goal{x=" + x + ",z=" + z + "}"; + } +} diff --git a/pathfinding/goals/GoalYLevel.java b/pathfinding/goals/GoalYLevel.java new file mode 100644 index 00000000..31d484da --- /dev/null +++ b/pathfinding/goals/GoalYLevel.java @@ -0,0 +1,32 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class GoalYLevel implements Goal { + final int level; + public GoalYLevel(int level) { + this.level = level; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getY() == level; + } + @Override + public double heuristic(BlockPos pos) { + return 20 * Math.abs(pos.getY() - level);//the number 20 was chosen somewhat randomly. + //TODO fix that + } + @Override + public String toString() { + return "Goal{y=" + level + "}"; + } +} diff --git a/schematic/Schematic.java b/schematic/Schematic.java new file mode 100644 index 00000000..616a8d64 --- /dev/null +++ b/schematic/Schematic.java @@ -0,0 +1,118 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.schematic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.Tuple; + +/** + * + * @author galdara + */ +public class Schematic { + private final HashMap schematicBlocks; + private final int width; + private final int height; + private final int length; + public Schematic(HashMap blocks, int width, int height, int length) { + schematicBlocks = blocks; + this.width = width; + this.height = height; + this.length = length; + } + public Schematic(Block type, int desiredWidth) { + if (type == null) { + throw new IllegalArgumentException(); + } + width = desiredWidth; + height = desiredWidth; + length = 1; + schematicBlocks = new HashMap(); + for (int i = 0; i < desiredWidth; i++) { + schematicBlocks.put(new BlockPos(i, 0, 0), type); + schematicBlocks.put(new BlockPos(i, desiredWidth - 1, 0), type); + schematicBlocks.put(new BlockPos(desiredWidth / 2, i, 0), type); + } + } + public Schematic(Block type, int desiredWidth, boolean rightFacing, boolean dots) { + if (type == null) { + throw new IllegalArgumentException(); + } + int size = (desiredWidth - 1) / 2; + width = size * 2 + 1; + height = 1; + length = width; + schematicBlocks = new HashMap(); + for (int x = 0; x < width; x++) { + schematicBlocks.put(new BlockPos(x, 0, size), type); + schematicBlocks.put(new BlockPos(size, 0, x), type); + } + for (int x = 0; x < size; x++) { + schematicBlocks.put(new BlockPos(rightFacing ? x + size + 1 : x, 0, 0), type); + schematicBlocks.put(new BlockPos(0, 0, rightFacing ? x : x + size + 1), type); + schematicBlocks.put(new BlockPos(width - 1, 0, rightFacing ? x + size + 1 : x), type); + schematicBlocks.put(new BlockPos(rightFacing ? x : x + size + 1, 0, width - 1), type); + } + if (dots) { + schematicBlocks.put(new BlockPos(size / 2, 0, size / 2), type); + schematicBlocks.put(new BlockPos(size / 2 + size + 1, 0, size / 2), type); + schematicBlocks.put(new BlockPos(size / 2 + size + 1, 0, size / 2 + size + 1), type); + schematicBlocks.put(new BlockPos(size / 2, 0, size / 2 + size + 1), type); + } + } + /** + * Tuple links the BlockPos and Block to one another. + * + * @param blockPos + * @return Tuple of BlockPos and Block + */ + public Tuple getTupleFromBlockPos(BlockPos blockPos) { + if (schematicBlocks.containsKey(blockPos)) { + return new Tuple(blockPos, schematicBlocks.get(blockPos)); + } + return null; + } + /** + * Gets given block type in schematic from a BlockPos + * + * @param blockPos + * @return + */ + public Block getBlockFromBlockPos(BlockPos blockPos) { + return schematicBlocks.get(blockPos); + } + /** + * Gives the length along the X axis + * + * @return Schematic width + */ + public int getWidth() { + return width; + } + /** + * Gives the height along the y axis + * + * @return Schematic height + */ + public int getHeight() { + return height; + } + /** + * Gives the length along the z axis + * + * @return Schematic length + */ + public int getLength() { + return length; + } + public ArrayList> getEntries() { + return new ArrayList(schematicBlocks.entrySet()); + } +} diff --git a/schematic/SchematicBuilder.java b/schematic/SchematicBuilder.java new file mode 100644 index 00000000..0c5fca11 --- /dev/null +++ b/schematic/SchematicBuilder.java @@ -0,0 +1,69 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.schematic; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map.Entry; +import baritone.Baritone; +import baritone.pathfinding.goals.GoalComposite; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.Tuple; + +/** + * + * @author leijurv + */ +public class SchematicBuilder { + ArrayList> plan = new ArrayList(); + BlockPos offset; + Schematic schematic; + public SchematicBuilder(Schematic schematic, BlockPos offset) { + this.schematic = schematic; + this.offset = offset; + for (Entry entry : schematic.getEntries()) { + plan.add(new Tuple(offset(entry.getKey()), entry.getValue())); + } + } + public void tick() { + HashSet goal = getAllBlocksToPlaceShiftedUp(); + //Out.log("Ticking " + goal); + if (goal != null) { + Baritone.goal = new GoalComposite(goal); + if (Baritone.currentPath == null && !Baritone.isThereAnythingInProgress) { + Baritone.findPathInNewThread(false); + } + } else { + //Out.gui("done building", Out.Mode.Standard); + } + } + public HashSet getAllBlocksToPlaceShiftedUp() { + HashSet toPlace = new HashSet(); + Block air = Block.getBlockById(0); + for (int y = 0; y < schematic.getHeight(); y++) { + for (int x = 0; x < schematic.getWidth(); x++) { + for (int z = 0; z < schematic.getLength(); z++) { + BlockPos inSchematic = new BlockPos(x, y, z); + BlockPos inWorld = offset(inSchematic); + Block current = Minecraft.getMinecraft().world.getBlockState(inWorld).getBlock(); + Block desired = schematic.getBlockFromBlockPos(inSchematic); + //Out.log(inSchematic + " " + current + " " + desired); + boolean currentlyAir = air.equals(current); + boolean shouldBeAir = desired == null || air.equals(desired); + if (currentlyAir && !shouldBeAir) { + toPlace.add(inWorld.up()); + } + } + } + } + return toPlace.isEmpty() ? null : toPlace; + } + private BlockPos offset(BlockPos original) { + return new BlockPos(original.getX() + offset.getX(), original.getY() + offset.getY(), original.getZ() + offset.getZ()); + } +} diff --git a/schematic/SchematicLoader.java b/schematic/SchematicLoader.java new file mode 100644 index 00000000..e1b205ea --- /dev/null +++ b/schematic/SchematicLoader.java @@ -0,0 +1,77 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.schematic; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author galdara + */ +public class SchematicLoader { + public static File schematicDir; + private static final HashMap cachedSchematics = new HashMap(); + private SchematicLoader() { + schematicDir = new File(Minecraft.getMinecraft().mcDataDir, "schematics"); + schematicDir.mkdir(); + for (File file : schematicDir.listFiles(new FileFilter() { + @Override + public boolean accept(File pathname) { + return pathname.getName().endsWith(".schematic"); + } + })) { + try { + cachedSchematics.put(file, loadFromFile(file)); + } catch (IOException ex) { + Logger.getLogger(SchematicLoader.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + public static SchematicLoader getLoader() { + return new SchematicLoader(); + } + public final Schematic loadFromFile(File nbtFile) throws FileNotFoundException, IOException { + if (cachedSchematics.containsKey(nbtFile)) { + return cachedSchematics.get(nbtFile); + } + FileInputStream fileInputStream = new FileInputStream(nbtFile); + NBTTagCompound compound = CompressedStreamTools.readCompressed(fileInputStream); + System.out.print(compound); + int height, width, length; + height = compound.getInteger("Height"); + width = compound.getInteger("Width"); + length = compound.getInteger("Length"); + byte[][][] blocks = new byte[width][height][length], data = new byte[width][height][length]; + byte[] rawBlocks = compound.getByteArray("Blocks"); + HashMap blocksMap = new HashMap(); + for (int y = 0; y < height; y++) { + for (int z = 0; z < length; z++) { + for (int x = 0; x < width; x++) { + int index = y * width * length + z * width + x; + blocks[x][y][z] = rawBlocks[index]; + blocksMap.put(new BlockPos(x, y, z), Block.getBlockById(rawBlocks[index])); + } + } + } + Out.log(blocksMap); + Schematic schematic = new Schematic(blocksMap, width, height, length); + cachedSchematics.put(nbtFile, schematic); + return schematic; + } +} diff --git a/strategy/EarlyGameStrategy.java b/strategy/EarlyGameStrategy.java new file mode 100644 index 00000000..16e338d9 --- /dev/null +++ b/strategy/EarlyGameStrategy.java @@ -0,0 +1,304 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.strategy; + +import baritone.movement.Combat; +import baritone.util.BlockPuncher; +import baritone.mining.MickeyMine; +import baritone.inventory.CraftingTask; +import baritone.util.Manager; +import baritone.util.ManagerTick; +import baritone.util.Out; +import baritone.inventory.SmeltingTask; +import net.minecraft.client.Minecraft; +import net.minecraft.item.Item; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemTool; + +/** + * goals: + * + * get dirt + * + * get wood + * + * make a crafting table + * + * make a wooden pickaxe + * + * get stone + * + * make a stone pickaxe + * + * get more stone + * + * make stone tools and a furnace + * + * go mining at level 36 + * + * craft torches + * + * smelt iron + * + * make iron pick and iron armor and an iron sword + * + * change mining level to 6 + * + * craft a diamond pickaxe + * + * @author leijurv + */ +public class EarlyGameStrategy extends ManagerTick { + static boolean gotWood_PHRASING = false; + static int WOOD_AMT = 16;//triggers stopping + static int MIN_WOOD_AMT = 1;//triggers getting more + static final int DIRT_AMT = 32; + static boolean gotDirt = false; + static boolean cobble = false; + @Override + protected boolean onTick0() { + if (!gotDirt) { + int dirt = countDirt(); + if (dirt >= DIRT_AMT) { + Out.gui("Done getting dirt", Out.Mode.Debug); + gotDirt = true; + return false; + } + if (!BlockPuncher.tick("dirt", "grass")) { + Out.gui("No dirt or grass nearby =(", Out.Mode.Debug); + } + return false; + } + int wood = countWood_PHRASING(); + if (wood >= WOOD_AMT) { + if (!gotWood_PHRASING) { + Out.gui("Done getting wood", Out.Mode.Debug); + } + gotWood_PHRASING = true; + } + if (wood < MIN_WOOD_AMT) { + if (gotWood_PHRASING) { + Out.gui("Getting more wood", Out.Mode.Debug); + } + gotWood_PHRASING = false; + } + if (!gotWood_PHRASING) { + if (!BlockPuncher.tick("log", "log2")) { + Out.gui("No wood nearby =(", Out.Mode.Debug); + } + return false; + } + boolean hasWooden = false; + boolean readyForMining = true; + boolean hasStone = craftTool(Item.getByNameOrId("minecraft:stone_pickaxe"), 1); + if (hasStone) { + dontCraft(Item.getByNameOrId("minecraft:wooden_pickaxe")); + } else { + hasWooden = craftTool(Item.getByNameOrId("minecraft:wooden_pickaxe"), 1); + } + readyForMining &= hasStone; + if (hasWooden || hasStone) { + if (!cobble) { + if (countCobble() > 16) { + cobble = true; + } else if (!BlockPuncher.tick("stone")) { + Out.gui("No stone nearby =(", Out.Mode.Debug); + } + } + } + if (!cobble) { + readyForMining = false; + } + if (cobble && gotDirt && countCobble() + countDirt() < 10) {//if we have already gotten cobble and dirt, but our amounts have run low, get more + if (!BlockPuncher.tick("dirt", "grass", "stone")) { + Out.gui("No dirt, grass, or stone", Out.Mode.Debug); + } + readyForMining = false; + } + if (countCobble() > 5) { + boolean axe = craftTool(Item.getByNameOrId("minecraft:stone_axe"), 1); + if (axe) { + WOOD_AMT = 64; + MIN_WOOD_AMT = 16; + } else { + readyForMining = false; + } + if (!craftTool(Item.getByNameOrId("minecraft:stone_shovel"), 1)) { + readyForMining = false; + } + if (!craftTool(Item.getByNameOrId("minecraft:stone_sword"), 1)) { + readyForMining = false; + } + } + if (countCobble() > 8) { + if (!craftTool(Item.getByNameOrId("minecraft:furnace"), 1)) { + readyForMining = false; + } + } + int miningLevel = MickeyMine.Y_IRON; + if (readyForMining) { + int amtIron = 0; + boolean ironPick = craftTool(Item.getByNameOrId("minecraft:iron_pickaxe"), 1); + if (ironPick) { + boolean ironSword = craftTool(Item.getByNameOrId("minecraft:iron_sword"), 1); + if (ironSword) { + boolean ironHelmet = craftTool(Item.getByNameOrId("minecraft:iron_helmet"), 1); + boolean ironChestplate = craftTool(Item.getByNameOrId("minecraft:iron_chestplate"), 1); + boolean ironLeggings = craftTool(Item.getByNameOrId("minecraft:iron_leggings"), 1); + boolean ironBoots = craftTool(Item.getByNameOrId("minecraft:iron_boots"), 1); + if (ironHelmet && ironChestplate && ironLeggings && ironBoots) { + miningLevel = MickeyMine.Y_DIAMOND; + } else { + amtIron = (!ironHelmet ? 5 : 0) + (!ironChestplate ? 8 : 0) + (!ironLeggings ? 7 : 0) + (!ironBoots ? 4 : 0); + } + } else { + amtIron = 2; + } + } else { + amtIron = 3; + } + int currIron = countItem("minecraft:iron_ingot"); + boolean hasOre = countItem("iron_ore") >= amtIron - currIron; + if (hasOre && currIron < amtIron) { + int tasksForIron = SmeltingTask.tasksFor(Item.getByNameOrId("iron_ingot")); + int newTask = amtIron - currIron - tasksForIron; + if (newTask > 0) { + new SmeltingTask(new ItemStack(Item.getByNameOrId("iron_ingot"), Math.min(countItem("iron_ore"), 64))).begin(); + } + readyForMining = false; + } + } + int numDiamonds = countItem("diamond"); + if (readyForMining && numDiamonds >= 1) { + if (craftTool(Item.getByNameOrId("diamond_pickaxe"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_sword"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_chestplate"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_leggings"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_helmet"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_boots"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_axe"), 1)) { + if (craftTool(Item.getByNameOrId("diamond_shovel"), 1)) { + Out.gui("My job here is done.", Out.Mode.Minimal); + cancel(); + return false; + } + } + } + } + } + } + } + } + } + Manager instance = Manager.getManager(MickeyMine.class); + if (readyForMining) { + MickeyMine.yLevel = miningLevel; + if (!instance.enabled()) { + instance.toggle(); + } + } else if (instance.enabled()) { + instance.toggle(); + } + return false; + } + public static boolean craftTool(Item tool, int amt) { + if (tool instanceof ItemTool) { + for (ItemStack stack : Minecraft.getMinecraft().player.inventory.mainInventory) { + if (stack == null) { + continue; + } + if (stack.getItem() instanceof ItemTool && stack.getItem().getClass() == tool.getClass()) { + ItemTool t = (ItemTool) (stack.getItem()); + if (t.getToolMaterial().getEfficiencyOnProperMaterial() >= ((ItemTool) tool).getToolMaterial().getEfficiencyOnProperMaterial()) { + //Out.gui("Saying has " + new ItemStack(tool, 0) + " because has " + stack); + return true; + } + } + } + return CraftingTask.ensureCraftingDesired(tool, amt); + } + if (tool instanceof ItemArmor) { + ItemArmor armor = (ItemArmor) tool; + for (ItemStack stack : Minecraft.getMinecraft().player.inventory.mainInventory) { + if (stack == null) { + continue; + } + if (stack.getItem() instanceof ItemArmor) { + ItemArmor a = (ItemArmor) (stack.getItem()); + if (a.armorType == armor.armorType) { + if (a.damageReduceAmount >= armor.damageReduceAmount) { + //Out.gui("Saying has " + new ItemStack(tool, 0) + " because has " + stack); + return true; + } + } + } + } + for (ItemStack stack : Minecraft.getMinecraft().player.inventory.armorInventory) { + if (stack == null) { + continue; + } + ItemArmor a = (ItemArmor) (stack.getItem()); + if (a.armorType == armor.armorType) { + if (a.damageReduceAmount >= armor.damageReduceAmount) { + //Out.gui("Saying has " + new ItemStack(tool, 0) + " because has " + stack); + return true; + } + } + } + } + return CraftingTask.ensureCraftingDesired(tool, amt); + } + public static void dontCraft(Item item) { + CraftingTask task = CraftingTask.findOrCreateCraftingTask(new ItemStack(item, 0)); + if (task.currentlyCrafting().stackSize > 0) { + task.decreaseNeededAmount(1); + } + } + public static int countItem(String s) { + Item item = Item.getByNameOrId(s); + int count = 0; + for (ItemStack stack : Minecraft.getMinecraft().player.inventory.mainInventory) { + if (stack == null) { + continue; + } + if (item.equals(stack.getItem())) { + count += stack.stackSize; + } + } + return count; + } + public static int countWood_PHRASING() { + return countItem("log") + countItem("log2"); + } + public static int countDirt() { + return countItem("dirt"); + } + public static int countCobble() { + return countItem("cobblestone"); + } + @Override + protected void onCancel() { + gotWood_PHRASING = false; + WOOD_AMT = 16; + MIN_WOOD_AMT = 1; + gotDirt = false; + cobble = false; + Combat.mobKilling = false; + SmeltingTask.coalOnly = false; + Manager.getManager(MickeyMine.class).cancel(); + } + @Override + protected void onStart() { + gotWood_PHRASING = false; + WOOD_AMT = 16; + MIN_WOOD_AMT = 1; + gotDirt = false; + cobble = false; + Combat.mobKilling = true; + SmeltingTask.coalOnly = true; + } +} diff --git a/ui/AimBow.java b/ui/AimBow.java new file mode 100644 index 00000000..ef507ff3 --- /dev/null +++ b/ui/AimBow.java @@ -0,0 +1,153 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.ui; + +import baritone.aiming.Arrow; +import baritone.aiming.Constants; +import baritone.aiming.Helper; +import baritone.ui.LookManager; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemBow; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.Color; +import org.lwjgl.util.ReadableColor; + +/** + * + * @author galdara + */ +public class AimBow { + public static BlockPos lastBlock = null; + public static boolean canHit(BlockPos target) { + return false; + } + public static void render(EntityPlayer player, float partialTicks) { + if (player.getCurrentEquippedItem() != null && player.getCurrentEquippedItem().getItem() instanceof ItemBow) { + drawArrowArc(player, new Arrow(Constants.BowConstants.bowFullDraw, Helper.degreesToRadians(player.rotationPitch * -1)), Color.BLUE, Color.RED, partialTicks); + } else { + lastBlock = null; + } + } + public static void drawArrowArc(EntityPlayer player, Arrow arrow, ReadableColor airColor, ReadableColor liquidColor, float partialTicks) { + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GL11.glLineWidth(0.5F); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + GlStateManager.color(airColor.getRed(), airColor.getGreen(), airColor.getBlue()); + double previousDist = 0; + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; + double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; + double previousX = d0 + previousDist - (double) (Math.cos(Helper.degreesToRadians(player.rotationYaw)) * 0.16F); + double previousY = arrow.getVerticalPositionAtHorizontalPosition(previousDist) + d1 + (double) player.getEyeHeight() - 0.10000000149011612D;; + double previousZ = d2 + previousDist - (double) (Math.sin(Helper.degreesToRadians(player.rotationYaw)) * 0.16F); + for (double dist = Constants.BowConstants.renderTrajectoryIncrement; dist < Constants.BowConstants.renderTrajectoryCutoff; dist += Constants.BowConstants.renderTrajectoryIncrement) { + BlockPos blockPos = new BlockPos(previousX, previousY, previousZ); + IBlockState blockState = Minecraft.getMinecraft().world.getBlockState(blockPos); + Block block = blockState.getBlock(); + if (Constants.BlockConstants.materialsPassable.contains(block.getMaterial())) { + if (Constants.BlockConstants.materialsLiquid.contains(block.getMaterial()) && arrow.isInAir) { + arrow.setIsInAir(false); + GlStateManager.color(liquidColor.getRed(), liquidColor.getGreen(), liquidColor.getBlue()); + } else if (!arrow.isInAir) { + arrow.setIsInAir(true); + GlStateManager.color(airColor.getRed(), airColor.getGreen(), airColor.getBlue()); + } + double currentX = (-Math.sin(Helper.degreesToRadians(player.rotationYaw)) * dist) + d0 - (double) (Math.cos((float) Helper.degreesToRadians(player.rotationYaw)) * 0.16F); + double currentY = arrow.getVerticalPositionAtHorizontalPosition(dist) + d1 + (double) player.getEyeHeight() - 0.10000000149011612D; + double currentZ = (Math.cos(Helper.degreesToRadians(player.rotationYaw)) * dist) + d2 - (double) (Math.sin((float) Helper.degreesToRadians(player.rotationYaw)) * 0.16F); + drawLine(player, previousX, previousY, previousZ, currentX, currentY, currentZ, partialTicks); + previousX = currentX; + previousY = currentY; + previousZ = currentZ; + } else { + drawSelectionBox(player, blockPos, partialTicks, (arrow.isInAir ? airColor : liquidColor)); + AimBow.lastBlock = blockPos; + break; + } + } + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + public static void drawLine(EntityPlayer player, double bp1x, double bp1y, double bp1z, double bp2x, double bp2y, double bp2z, float partialTicks) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; + double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(bp1x - d0, bp1y - d1, bp1z - d2).endVertex(); + worldrenderer.pos(bp2x - d0, bp2y - d1, bp2z - d2).endVertex(); + worldrenderer.pos(bp2x - d0, bp2y - d1, bp2z - d2).endVertex(); + worldrenderer.pos(bp1x - d0, bp1y - d1, bp1z - d2).endVertex(); + worldrenderer.pos(bp1x - d0, bp1y - d1, bp1z - d2).endVertex(); + tessellator.draw(); + } + public static void drawSelectionBox(EntityPlayer player, BlockPos blockpos, float partialTicks, ReadableColor color) { + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.color(color.getRed(), color.getGreen(), color.getBlue(), 0.4F); + GL11.glLineWidth(5.0F); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + float f = 0.002F; + //BlockPos blockpos = movingObjectPositionIn.getBlockPos(); + Block block = Minecraft.getMinecraft().world.getBlockState(blockpos).getBlock(); + if (block.equals(Blocks.air)) { + block = Blocks.dirt; + } + block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().world, blockpos); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; + double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; + AxisAlignedBB toDraw = block.getSelectedBoundingBox(Minecraft.getMinecraft().world, blockpos).expand(0.0020000000949949026D, 0.0020000000949949026D, 0.0020000000949949026D).offset(-d0, -d1, -d2); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + tessellator.draw(); + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + tessellator.draw(); + worldrenderer.begin(1, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex(); + tessellator.draw(); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + public static void aimAtEntity(Entity entity) { + LookManager.setDesiredYaw((float) Math.atan2(entity.posX - Minecraft.getMinecraft().player.posX, entity.posZ - Minecraft.getMinecraft().player.posZ)); + } +} diff --git a/ui/GuiEscMenu.java b/ui/GuiEscMenu.java new file mode 100644 index 00000000..cc5e0d7c --- /dev/null +++ b/ui/GuiEscMenu.java @@ -0,0 +1,93 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.ui; + +import java.io.IOException; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiIngameMenu; +import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.gui.GuiMultiplayer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.resources.I18n; +import net.minecraft.realms.RealmsBridge; + +/** + * + * @author avecowa + */ +public class GuiEscMenu extends GuiScreen { + private int field_146445_a; + private int field_146444_f; + /** + * Adds the buttons (and other controls) to the screen in question. Called + * when the GUI is displayed and when the window resizes, the buttonList is + * cleared beforehand. + */ + public void initGui() { + this.field_146445_a = 0; + this.buttonList.clear(); + int i = -16; + int j = 98; + int returnWidth = 130; + int returnHeight = 20; + this.buttonList.add(new GuiButton(1, /*this.width / 2 - returnWidth / 2*/ this.width - returnWidth - 10, 10 + 30, returnWidth, returnHeight, I18n.format("menu.returnToMenu", new Object[0]))); + this.buttonList.add(new GuiButton(0, /*this.width / 2 - returnWidth / 2*/ this.width - returnWidth - 10, 10, returnWidth, returnHeight, I18n.format("menu.options", new Object[0]))); + if (!this.mc.isIntegratedServerRunning()) { + ((GuiButton) this.buttonList.get(0)).displayString = I18n.format("menu.disconnect", new Object[0]); + } + /* this.buttonList.add(new GuiButton(4, this.width / 2 - 100, this.height / 4 + 24 + i, I18n.format("menu.returnToGame", new Object[0]))); + this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + i, 98, 20, I18n.format("menu.options", new Object[0]))); + GuiButton guibutton; + this.buttonList.add(guibutton = new GuiButton(7, this.width / 2 + 2, this.height / 4 + 96 + i, 98, 20, I18n.format("menu.shareToLan", new Object[0]))); + this.buttonList.add(new GuiButton(5, this.width / 2 - 100, this.height / 4 + 48 + i, 98, 20, I18n.format("gui.achievements", new Object[0]))); + this.buttonList.add(new GuiButton(6, this.width / 2 + 2, this.height / 4 + 48 + i, 98, 20, I18n.format("gui.stats", new Object[0]))); + guibutton.enabled = this.mc.isSingleplayer() && !this.mc.getIntegratedServer().getPublic();*/ + } + /** + * Called by the controls from the buttonList when activated. (Mouse pressed + * for buttons) + */ + protected void actionPerformed(GuiButton button) throws IOException { + switch (button.id) { + case 0: + this.mc.displayGuiScreen(new GuiIngameMenu()); + break; + case 1: + boolean flag = this.mc.isIntegratedServerRunning(); + boolean flag1 = this.mc.func_181540_al(); + button.enabled = false; + this.mc.world.sendQuittingDisconnectingPacket(); + this.mc.loadWorld((WorldClient) null); + if (flag) { + this.mc.displayGuiScreen(new GuiMainMenu()); + } else if (flag1) { + RealmsBridge realmsbridge = new RealmsBridge(); + realmsbridge.switchToRealms(new GuiMainMenu()); + } else { + this.mc.displayGuiScreen(new GuiMultiplayer(new GuiMainMenu())); + } + default: + break; + } + } + /** + * Called from the main game loop to update the screen. + */ + public void updateScreen() { + super.updateScreen(); + ++this.field_146444_f; + } + /** + * Draws the screen and all the components in it. Args : mouseX, mouseY, + * renderPartialTicks + */ + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + //this.drawDefaultBackground(); NOPE + this.drawCenteredString(this.fontRendererObj, "hit ESC to return to game", this.width / 2, 5, 16777215); + super.drawScreen(mouseX, mouseY, partialTicks); + } +} diff --git a/ui/LookManager.java b/ui/LookManager.java new file mode 100644 index 00000000..f6a09e56 --- /dev/null +++ b/ui/LookManager.java @@ -0,0 +1,345 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.ui; + +import java.util.ArrayList; +import java.util.Random; +import baritone.pathfinding.goals.GoalXZ; +import baritone.util.Manager; +import net.minecraft.block.Block; +import net.minecraft.block.BlockFire; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +/** + * + * @author leijurv + */ +public class LookManager extends Manager { + public static boolean randomLooking = true; + static final float MAX_YAW_CHANGE_PER_TICK = 360 / 20; + static final float MAX_PITCH_CHANGE_PER_TICK = 360 / 20; + static float previousYaw = 0; + static float previousPitch = 0; + /** + * Something with smoothing between ticks + */ + static float desiredNextYaw = 0; + static float desiredNextPitch = 0; + /** + * The desired yaw, as set by whatever action is happening. Remember to also + * set lookingYaw to true if you really want the yaw to change + * + */ + static float desiredYaw; + /** + * The desired pitch, as set by whatever action is happening. Remember to + * also set lookingPitch to true if you really want the yaw to change + * + */ + static float desiredPitch; + /** + * Set to true if the action wants the player's yaw to be moved towards + * desiredYaw + */ + static boolean lookingYaw = false; + /** + * Set to true if the action wants the player's pitch to be moved towards + * desiredPitch + */ + static boolean lookingPitch = false; + public static void frame(float partialTicks) { + //Out.log("Part: " + partialTicks); + if (Minecraft.getMinecraft() == null || Minecraft.getMinecraft().player == null) { + return; + } + if (lookingPitch) { + Minecraft.getMinecraft().player.rotationPitch = (desiredNextPitch - previousPitch) * partialTicks + previousPitch; + } + if (lookingYaw) { + Minecraft.getMinecraft().player.rotationYaw = (desiredNextYaw - previousYaw) * partialTicks + previousYaw; + } + } + /** + * Because I had to do it the janky way + */ + private static final double[][] BLOCK_SIDE_MULTIPLIERS = {{0, 0.5, 0.5}, {1, 0.5, 0.5}, {0.5, 0, 0.5}, {0.5, 1, 0.5}, {0.5, 0.5, 0}, {0.5, 0.5, 1}}; + /** + * Called by our code in order to look in the direction of the center of a + * block + * + * @param p the position to look at + * @param alsoDoPitch whether to set desired pitch or just yaw + * @return is the actual player yaw (and actual player pitch, if alsoDoPitch + * is true) within ANGLE_THRESHOLD (currently 7°) of looking straight at + * this block? + */ + public static boolean lookAtBlock(BlockPos p, boolean alsoDoPitch) { + if (couldIReachCenter(p)) { + return lookAtCenterOfBlock(p, alsoDoPitch); + } + Block b = Minecraft.getMinecraft().world.getBlockState(p).getBlock(); + for (double[] mult : BLOCK_SIDE_MULTIPLIERS) { + double xDiff = b.getBlockBoundsMinX() * mult[0] + b.getBlockBoundsMaxX() * (1 - mult[0]);//lol + double yDiff = b.getBlockBoundsMinY() * mult[1] + b.getBlockBoundsMaxY() * (1 - mult[1]); + double zDiff = b.getBlockBoundsMinZ() * mult[2] + b.getBlockBoundsMaxZ() * (1 - mult[2]); + double x = p.getX() + xDiff; + double y = p.getY() + yDiff; + double z = p.getZ() + zDiff; + if (couldIReachByLookingAt(p, x, y, z)) { + return lookAtCoords(x, y, z, alsoDoPitch); + } + } + return lookAtCenterOfBlock(p, alsoDoPitch); + } + public static boolean lookAtCenterOfBlock(BlockPos p, boolean alsoDoPitch) { + Block b = Minecraft.getMinecraft().world.getBlockState(p).getBlock(); + double xDiff = (b.getBlockBoundsMinX() + b.getBlockBoundsMaxX()) / 2; + double yDiff = (b.getBlockBoundsMinY() + b.getBlockBoundsMaxY()) / 2; + double zDiff = (b.getBlockBoundsMinZ() + b.getBlockBoundsMaxZ()) / 2; + if (b instanceof BlockFire) {//look at bottom of fire when putting it out + yDiff = 0; + } + double x = p.getX() + xDiff; + double y = p.getY() + yDiff; + double z = p.getZ() + zDiff; + return lookAtCoords(x, y, z, alsoDoPitch); + } + /** + * The threshold for how close it tries to get to looking straight at things + */ + public static final float ANGLE_THRESHOLD = 7; + public static boolean couldIReach(BlockPos pos) { + if (couldIReachCenter(pos)) { + return true; + } + Block b = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + for (double[] mult : BLOCK_SIDE_MULTIPLIERS) { + double xDiff = b.getBlockBoundsMinX() * mult[0] + b.getBlockBoundsMaxX() * (1 - mult[0]); + double yDiff = b.getBlockBoundsMinY() * mult[1] + b.getBlockBoundsMaxY() * (1 - mult[1]); + double zDiff = b.getBlockBoundsMinZ() * mult[2] + b.getBlockBoundsMaxZ() * (1 - mult[2]); + double x = pos.getX() + xDiff; + double y = pos.getY() + yDiff; + double z = pos.getZ() + zDiff; + if (couldIReachByLookingAt(pos, x, y, z)) { + return true; + } + } + return false; + } + public static boolean couldIReachCenter(BlockPos pos) { + float[] pitchAndYaw = pitchAndYawToCenter(pos); + MovingObjectPosition blah = raytraceTowards(pitchAndYaw); + return blah != null && blah.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && blah.getBlockPos().equals(pos); + } + public static boolean couldIReach(BlockPos pos, EnumFacing dir) { + BlockPos side = pos.offset(dir); + double faceX = (pos.getX() + side.getX() + 1.0D) * 0.5D; + double faceY = (pos.getY() + side.getY()) * 0.5D; + double faceZ = (pos.getZ() + side.getZ() + 1.0D) * 0.5D; + MovingObjectPosition blah = raytraceTowards(faceX, faceY, faceZ); + return blah != null && blah.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && blah.getBlockPos().equals(pos) && blah.sideHit == dir; + } + public static MovingObjectPosition raytraceTowards(double x, double y, double z) { + return raytraceTowards(pitchAndYaw(x, y, z)); + } + public static MovingObjectPosition raytraceTowards(float[] pitchAndYaw) { + float yaw = pitchAndYaw[0]; + float pitch = pitchAndYaw[1]; + double blockReachDistance = (double) Minecraft.getMinecraft().playerController.getBlockReachDistance(); + Vec3 vec3 = Minecraft.getMinecraft().player.getPositionEyes(1.0F); + Vec3 vec31 = getVectorForRotation(pitch, yaw); + Vec3 vec32 = vec3.addVector(vec31.xCoord * blockReachDistance, vec31.yCoord * blockReachDistance, vec31.zCoord * blockReachDistance); + MovingObjectPosition blah = Minecraft.getMinecraft().world.rayTraceBlocks(vec3, vec32, false, false, true); + return blah; + } + public static boolean couldIReachByLookingAt(BlockPos pos, double x, double y, double z) { + MovingObjectPosition blah = raytraceTowards(x, y, z); + return blah != null && blah.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && blah.getBlockPos().equals(pos); + } + public static Vec3 getVectorForRotation(float pitch, float yaw) {//shamelessly copied from Entity.java + float f = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI); + float f1 = MathHelper.sin(-yaw * 0.017453292F - (float) Math.PI); + float f2 = -MathHelper.cos(-pitch * 0.017453292F); + float f3 = MathHelper.sin(-pitch * 0.017453292F); + return new Vec3((double) (f1 * f2), (double) f3, (double) (f * f2)); + } + public static GoalXZ fromAngleAndDirection(double distance) { + double theta = ((double) Minecraft.getMinecraft().player.rotationYaw) * Math.PI / 180D; + double x = Minecraft.getMinecraft().player.posX - Math.sin(theta) * distance; + double z = Minecraft.getMinecraft().player.posZ + Math.cos(theta) * distance; + return new GoalXZ((int) x, (int) z); + } + public static boolean lookingYaw() { + return lookingYaw; + } + static double SPEED = 1000; + /** + * Smoothly moves between random pitches and yaws every second + * + * @return + */ + public static float[] getRandom() { + long now = (long) Math.ceil(((double) System.currentTimeMillis()) / SPEED); + now *= SPEED; + long prev = now - (long) SPEED; + float frac = (System.currentTimeMillis() - prev) / ((float) SPEED);//fraction between previous second and next + Random prevR = new Random(prev);//fite me + Random nowR = new Random(now); + float prevFirst = prevR.nextFloat() * 10 - 5; + float prevSecond = prevR.nextFloat() * 10 - 5; + float nowFirst = nowR.nextFloat() * 10 - 5; + float nowSecond = nowR.nextFloat() * 10 - 5; + float first = prevFirst + frac * (nowFirst - prevFirst);//smooth between previous and next second + float second = prevSecond + frac * (nowSecond - prevSecond); + return new float[]{first, second}; + } + public static float[] pitchAndYawToCenter(BlockPos p) { + Block b = Minecraft.getMinecraft().world.getBlockState(p).getBlock(); + double xDiff = (b.getBlockBoundsMinX() + b.getBlockBoundsMaxX()) / 2; + double yolo = (b.getBlockBoundsMinY() + b.getBlockBoundsMaxY()) / 2; + double zDiff = (b.getBlockBoundsMinZ() + b.getBlockBoundsMaxZ()) / 2; + if (b instanceof BlockFire) {//look at bottom of fire when putting it out + yolo = 0; + } + double x = p.getX() + xDiff; + double y = p.getY() + yolo; + double z = p.getZ() + zDiff; + return pitchAndYaw(x, y, z); + } + public static float[] pitchAndYaw(double x, double y, double z) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + double yDiff = (thePlayer.posY + 1.62) - y;//lol + double yaw = Math.atan2(thePlayer.posX - x, -thePlayer.posZ + z); + double dist = Math.sqrt((thePlayer.posX - x) * (thePlayer.posX - x) + (-thePlayer.posZ + z) * (-thePlayer.posZ + z)); + double pitch = Math.atan2(yDiff, dist); + return new float[]{(float) (yaw * 180 / Math.PI), (float) (pitch * 180 / Math.PI)}; + } + static ArrayList sketchiness = new ArrayList<>(); + public static void setDesiredYaw(float y) { + sketchiness.add(new Exception("Desired yaw already set!")); + if (lookingYaw) { + /*for (Exception ex : sketchiness) { + Logger.getLogger(LookManager.class.getName()).log(Level.SEVERE, null, ex);//print out everyone who has tried to set the desired yaw this tick to show the conflict + }*/ + sketchiness.clear(); + return; + } + desiredYaw = y; + lookingYaw = true; + } + /** + * Look at coordinates + * + * @param x + * @param y + * @param z + * @param alsoDoPitch also adjust the pitch? if false, y is ignored + * @return is the actual player yaw (and actual player pitch, if alsoDoPitch + * is true) within ANGLE_THRESHOLD (currently 7°) of looking straight at + * these coordinates? + */ + public static boolean lookAtCoords(double x, double y, double z, boolean alsoDoPitch) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + double yDiff = (thePlayer.posY + 1.62) - y; + double yaw = Math.atan2(thePlayer.posX - x, -thePlayer.posZ + z); + double dist = Math.sqrt((thePlayer.posX - x) * (thePlayer.posX - x) + (-thePlayer.posZ + z) * (-thePlayer.posZ + z)); + double pitch = Math.atan2(yDiff, dist); + setDesiredYaw((float) (yaw * 180 / Math.PI)); + float yawDist = Math.abs(desiredYaw - thePlayer.rotationYaw); + boolean withinRange = yawDist < ANGLE_THRESHOLD || yawDist > 360 - ANGLE_THRESHOLD; + if (alsoDoPitch) { + lookingPitch = true; + desiredPitch = (float) (pitch * 180 / Math.PI); + float pitchDist = Math.abs(desiredPitch - thePlayer.rotationPitch); + withinRange = withinRange && (pitchDist < ANGLE_THRESHOLD || pitchDist > 360 - ANGLE_THRESHOLD); + } + return withinRange; + } + @Override + public void onTickPre() { + if (lookingYaw) { + Minecraft.getMinecraft().player.rotationYaw = desiredNextYaw; + } + if (lookingPitch) { + Minecraft.getMinecraft().player.rotationPitch = desiredNextPitch; + } + lookingYaw = false; + sketchiness.clear(); + lookingPitch = false; + } + public static void nudgeToLevel() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().player; + if (!lookingPitch) { + if (thePlayer.rotationPitch < -20) { + thePlayer.rotationPitch++; + } else if (thePlayer.rotationPitch > 20) { + thePlayer.rotationPitch--; + } + } + } + @Override + public void onTickPost() { + if (randomLooking) { + desiredYaw += getRandom()[0]; + desiredPitch += getRandom()[1]; + } + if (desiredPitch > 90) { + desiredPitch = 90; + } + if (desiredPitch < -90) { + desiredPitch = -90; + } + if (lookingYaw) { + previousYaw = Minecraft.getMinecraft().player.rotationYaw; + desiredYaw += 360; + desiredYaw %= 360; + float yawDistance = Minecraft.getMinecraft().player.rotationYaw - desiredYaw; + if (yawDistance > 180) { + yawDistance -= 360; + } else if (yawDistance < -180) { + yawDistance += 360; + } + if (Math.abs(yawDistance) > MAX_YAW_CHANGE_PER_TICK) { + yawDistance = Math.signum(yawDistance) * MAX_YAW_CHANGE_PER_TICK; + } + desiredNextYaw = Minecraft.getMinecraft().player.rotationYaw - yawDistance; + } + if (lookingPitch) { + previousPitch = Minecraft.getMinecraft().player.rotationPitch; + desiredPitch += 360; + desiredPitch %= 360; + float pitchDistance = Minecraft.getMinecraft().player.rotationPitch - desiredPitch; + if (pitchDistance > 180) { + pitchDistance -= 360; + } else if (pitchDistance < -180) { + pitchDistance += 360; + } + if (Math.abs(pitchDistance) > MAX_PITCH_CHANGE_PER_TICK) { + pitchDistance = Math.signum(pitchDistance) * MAX_PITCH_CHANGE_PER_TICK; + } + desiredNextPitch = Minecraft.getMinecraft().player.rotationPitch - pitchDistance; + } + } + @Override + protected void onTick() { + } + @Override + protected void onCancel() { + } + @Override + protected void onStart() { + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } +} diff --git a/ui/PathRenderer.java b/ui/PathRenderer.java new file mode 100644 index 00000000..d2a912f0 --- /dev/null +++ b/ui/PathRenderer.java @@ -0,0 +1,248 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.ui; + +import java.awt.Color; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.Baritone; +import baritone.pathfinding.Path; +import baritone.pathfinding.PathFinder; +import baritone.pathfinding.actions.Action; +import baritone.util.FakeArrow; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import org.lwjgl.opengl.GL11; + +/** + * + * @author leijurv + */ +public class PathRenderer { + public static void render(EntityPlayer player, float partialTicks) { + if (Baritone.currentPath != null) { + drawPath(Baritone.currentPath, player, partialTicks, Color.RED); + for (BlockPos pos : Baritone.currentPath.toMine()) { + drawSelectionBox(player, pos, partialTicks, Color.RED); + } + for (BlockPos pos : Baritone.currentPath.toPlace()) { + drawSelectionBox(player, pos, partialTicks, Color.GREEN); + } + } + if (Baritone.nextPath != null) { + drawPath(Baritone.nextPath, player, partialTicks, Color.GREEN); + for (BlockPos pos : Baritone.nextPath.toMine()) { + drawSelectionBox(player, pos, partialTicks, Color.RED); + } + for (BlockPos pos : Baritone.nextPath.toPlace()) { + drawSelectionBox(player, pos, partialTicks, Color.GREEN); + } + } + try { + if (PathFinder.currentlyRunning != null) { + Path p = PathFinder.currentlyRunning.getTempSolution(); + if (p != null) { + drawPath(p, player, partialTicks, Color.BLUE); + Path mr = PathFinder.currentlyRunning.getMostRecentNodeConsidered(); + if (mr != null) { + drawPath(mr, player, partialTicks, Color.CYAN); + drawSelectionBox(player, mr.end, partialTicks, Color.CYAN); + } + } + } + } catch (Exception ex) { + Logger.getLogger(PathRenderer.class.getName()).log(Level.SEVERE, null, ex); + } + if (!Baritone.sketchytracer) { + return; + } + try { + ItemStack holding = Minecraft.getMinecraft().player.inventory.mainInventory[Minecraft.getMinecraft().player.inventory.currentItem]; + if (holding != null && (holding.getItem() instanceof ItemBow)) { + if (Minecraft.getMinecraft().player.getItemInUse() != null) { + int i = holding.getItem().getMaxItemUseDuration(holding) - Minecraft.getMinecraft().player.getItemInUseCount(); + float f = (float) i / 20.0F; + f = (f * f + f * 2.0F) / 3.0F; + if ((double) f < 0.1D) { + return; + } + if (f > 1.0F) { + f = 1.0F; + } + drawBowStuff(player, partialTicks, f * 2); + } else { + drawBowStuff(player, partialTicks, 2.0F); + } + } + } catch (Exception ex) { + Logger.getLogger(PathRenderer.class.getName()).log(Level.SEVERE, null, ex); + } + } + public static void drawBowStuff(EntityPlayer player, float partialTicks, float strength) { + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + FakeArrow ar1 = new FakeArrow(Minecraft.getMinecraft().world, Minecraft.getMinecraft().player, strength, partialTicks); + for (int i = 0; i < 200; i++) { + ar1.onUpdate(); + } + Color color = ar1.didIHitAnEntity ? Color.RED : Color.BLACK; + GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); + GL11.glLineWidth(3.0F); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + FakeArrow ar = new FakeArrow(Minecraft.getMinecraft().world, Minecraft.getMinecraft().player, strength, partialTicks); + double prevX = ar.posX; + double prevY = ar.posY; + double prevZ = ar.posZ; + for (int i = 0; i < 200; i++) { + ar.onUpdate(); + double currX = ar.posX; + double currY = ar.posY; + double currZ = ar.posZ; + drawLine(Minecraft.getMinecraft().player, prevX - 0.5, prevY - 0.5, prevZ - 0.5, currX - 0.5, currY - 0.5, currZ - 0.5, partialTicks); + prevX = currX; + prevY = currY; + prevZ = currZ; + } + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + public static void drawPath(Path path, EntityPlayer player, float partialTicks, Color color) { + /*for (BlockPos pos : path.path) { + drawSelectionBox(player, pos, partialTicks, color); + }*/ + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); + GL11.glLineWidth(3.0F); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + boolean[] cornerFirstHalf = new boolean[path.path.size()]; + boolean[] cornerSecondHalf = new boolean[path.path.size()]; + for (int i = 0; i < path.path.size() - 2; i++) { + BlockPos a = path.path.get(i); + BlockPos b = path.path.get(i + 1); + BlockPos c = path.path.get(i + 2); + if (a.getY() != b.getY() || b.getY() != c.getY()) { + continue; + } + if (b.getX() - a.getX() == c.getX() - b.getX() && b.getZ() - a.getZ() == c.getZ() - b.getZ()) { + continue; + } + if (a.getX() != b.getX() && a.getZ() != b.getZ()) { + continue; + } + if (b.getX() != c.getX() && b.getZ() != c.getZ()) { + continue; + } + BlockPos corner = new BlockPos(c.getX() - b.getX() + a.getX(), a.getY(), c.getZ() - b.getZ() + a.getZ()); + if (Action.avoidWalkingInto(corner) || Action.avoidWalkingInto(corner.up())) { + continue; + } + cornerFirstHalf[i] = true; + cornerSecondHalf[i + 1] = true; + double bp1x = (a.getX() + b.getX()) * 0.5D; + double bp1z = (a.getZ() + b.getZ()) * 0.5D; + double bp2x = (c.getX() + b.getX()) * 0.5D; + double bp2z = (c.getZ() + b.getZ()) * 0.5D; + drawLine(player, bp1x, a.getY(), bp1z, bp2x, a.getY(), bp2z, partialTicks); + } + for (int i = 0; i < path.path.size() - 1; i++) { + BlockPos a = path.path.get(i); + BlockPos b = path.path.get(i + 1); + if (cornerFirstHalf[i] && !cornerSecondHalf[i]) { + drawLine(player, a.getX(), a.getY(), a.getZ(), (b.getX() + a.getX()) * 0.5D, b.getY(), (b.getZ() + a.getZ()) * 0.5D, partialTicks); + } + if (cornerSecondHalf[i] && !cornerFirstHalf[i]) { + drawLine(player, (a.getX() + b.getX()) * 0.5D, a.getY(), (a.getZ() + b.getZ()) * 0.5D, b.getX(), b.getY(), b.getZ(), partialTicks); + } + if (!cornerFirstHalf[i] && !cornerSecondHalf[i]) { + drawLine(player, a.getX(), a.getY(), a.getZ(), b.getX(), b.getY(), b.getZ(), partialTicks); + } else { + GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.1F); + drawLine(player, a.getX(), a.getY(), a.getZ(), b.getX(), b.getY(), b.getZ(), partialTicks); + GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); + } + } + //GlStateManager.color(0.0f, 0.0f, 0.0f, 0.4f); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + public static void drawLine(EntityPlayer player, double bp1x, double bp1y, double bp1z, double bp2x, double bp2y, double bp2z, float partialTicks) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; + double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex(); + worldrenderer.pos(bp2x + 0.5D - d0, bp2y + 0.5D - d1, bp2z + 0.5D - d2).endVertex(); + worldrenderer.pos(bp2x + 0.5D - d0, bp2y + 0.53D - d1, bp2z + 0.5D - d2).endVertex(); + worldrenderer.pos(bp1x + 0.5D - d0, bp1y + 0.53D - d1, bp1z + 0.5D - d2).endVertex(); + worldrenderer.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex(); + tessellator.draw(); + } + public static void drawSelectionBox(EntityPlayer player, BlockPos blockpos, float partialTicks, Color color) { + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); + GL11.glLineWidth(5.0F); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + float f = 0.002F; + //BlockPos blockpos = movingObjectPositionIn.getBlockPos(); + Block block = Minecraft.getMinecraft().world.getBlockState(blockpos).getBlock(); + if (block.equals(Blocks.air)) { + block = Blocks.dirt; + } + block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().world, blockpos); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; + double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; + AxisAlignedBB toDraw = block.getSelectedBoundingBox(Minecraft.getMinecraft().world, blockpos).expand(0.0020000000949949026D, 0.0020000000949949026D, 0.0020000000949949026D).offset(-d0, -d1, -d2); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + tessellator.draw(); + worldrenderer.begin(3, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + tessellator.draw(); + worldrenderer.begin(1, DefaultVertexFormats.POSITION); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex(); + worldrenderer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex(); + tessellator.draw(); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } +} diff --git a/ui/Screenshot.java b/ui/Screenshot.java new file mode 100644 index 00000000..110dfdc6 --- /dev/null +++ b/ui/Screenshot.java @@ -0,0 +1,257 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.ui; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.util.Manager; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureUtil; +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +/** + * I swear, this *isn't* copied from net.minecraft.util.ScreenShotHelper. Pinky + * promise. + * + * @author leijurv + */ +public class Screenshot extends Manager { + static ExecutorService lol = Executors.newCachedThreadPool(); + + public static class Dank { + E curr; + Dank next; + } + static final Object valCacheLock = new Object(); + static Dank valCache = null; + public static int[] getInt(int size) { + while (true) { + int[] blah = popInt(); + if (blah == null) { + System.out.println("CREATING INT ARRAY OF SIZE " + size); + return new int[size]; + } + if (blah.length >= size) { + if (blah.length > size) { + if (new Random().nextInt(100) == 0) { + continue; + } + } + return blah; + } + } + } + public static void pushInt(int[] blah) { + synchronized (valCacheLock) { + Dank xd = new Dank<>(); + xd.next = valCache; + xd.curr = blah; + valCache = xd; + } + } + public static int[] popInt() { + synchronized (valCacheLock) { + if (valCache == null) { + return null; + } + int[] result = valCache.curr; + valCache = valCache.next; + return result; + } + } + static final Object bufCacheLock = new Object(); + static Dank bufCache = null; + public static IntBuffer getBuf(int size) { + while (true) { + IntBuffer blah = popBuf(); + if (blah == null) { + System.out.println("CREATING INT BUFFER OF SIZE " + size); + return BufferUtils.createIntBuffer(size); + } + if (blah.capacity() >= size) { + if (blah.capacity() > size) { + if (new Random().nextInt(100) == 0) { + continue; + } + } + return blah; + } + } + } + public static void pushBuf(IntBuffer blah) { + blah.clear(); + synchronized (bufCacheLock) { + Dank xd = new Dank<>(); + xd.next = bufCache; + xd.curr = blah; + bufCache = xd; + } + } + public static IntBuffer popBuf() { + synchronized (bufCacheLock) { + if (bufCache == null) { + return null; + } + IntBuffer result = bufCache.curr; + bufCache = bufCache.next; + return result; + } + } + public static void screenshot() { + if (currPixVal != null) { + System.out.println("Skipping"); + return; + } + int width = Minecraft.getMinecraft().displayWidth; + int height = Minecraft.getMinecraft().displayHeight; + int i = width * height; + final IntBuffer pixelBuffer = getBuf(i); + GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1); + GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); + GL11.glReadPixels(0, 0, width, height, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer); + new Thread() { + @Override + public void run() { + int[] pixelValues = getInt(i); + pixelBuffer.get(pixelValues); + TextureUtil.processPixelValues(pixelValues, width, height); + /*BufferedImage bufferedimage; + bufferedimage = new BufferedImage(width, height, 1); + bufferedimage.setRGB(0, 0, width, height, pixelValues, 0, width);*/ + pushBuf(pixelBuffer); + boolean hasSockets; + synchronized (socketsLock) { + hasSockets = !sockets.isEmpty(); + } + if (!hasSockets) { + pushInt(pixelValues); + return; + } + synchronized (currPixLock) { + if (currPixVal != null) { + pushInt(currPixVal); + } + currPixVal = pixelValues; + currWidth = width; + currHeight = height; + } + } + }.start(); + } + static final Object currPixLock = new Object(); + static int[] currPixVal = null; + static int currWidth = 0; + static int currHeight = 0; + @Override + protected void onTick() { + boolean hasSockets; + synchronized (socketsLock) { + hasSockets = !sockets.isEmpty(); + } + if (hasSockets) { + long bef = System.currentTimeMillis(); + screenshot(); + long aft = System.currentTimeMillis(); + if (aft != bef) { + System.out.println("Took " + (aft - bef)); + } + } + } + @Override + protected void onCancel() { + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + static final Object socketsLock = new Object(); + static ArrayList sockets = new ArrayList<>(); + @Override + protected void onStart() { + try { + ServerSocket blah = new ServerSocket(5021); + new Thread() { + @Override + public void run() { + try { + while (true) { + Thread.sleep(100); + synchronized (socketsLock) { + if (sockets.isEmpty()) { + continue; + } + } + int width; + int height; + int[] pixelValues; + synchronized (currPixLock) { + if (currPixVal == null) { + continue; + } + width = currWidth; + height = currHeight; + pixelValues = currPixVal; + currPixVal = null; + } + ArrayList tmpCopy; + synchronized (socketsLock) { + tmpCopy = sockets; + } + for (Socket socket : tmpCopy) { + try { + long start = System.currentTimeMillis(); + OutputStream o = socket.getOutputStream(); + System.out.println("Write " + width + " " + height + " " + pixelValues.length); + new DataOutputStream(o).writeInt(width); + new DataOutputStream(o).writeInt(height); + new ObjectOutputStream(o).writeObject(pixelValues); + long end = System.currentTimeMillis(); + System.out.println("Written in " + (end - start)); + } catch (IOException ex) { + Logger.getLogger(Screenshot.class.getName()).log(Level.SEVERE, null, ex); + synchronized (socketsLock) { + sockets.remove(socket); + } + } + } + pushInt(pixelValues); + } + } catch (InterruptedException ex) { + Logger.getLogger(Screenshot.class.getName()).log(Level.SEVERE, null, ex); + } + } + }.start(); + new Thread() { + @Override + public void run() { + try { + while (true) { + Socket socket = blah.accept(); + synchronized (socketsLock) { + sockets.add(socket); + } + } + } catch (IOException ex) { + Logger.getLogger(Screenshot.class.getName()).log(Level.SEVERE, null, ex); + } + } + }.start(); + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } catch (IOException ex) { + Logger.getLogger(Screenshot.class.getName()).log(Level.SEVERE, null, ex); + } + } +} diff --git a/util/Autorun.java b/util/Autorun.java new file mode 100644 index 00000000..c6464ea6 --- /dev/null +++ b/util/Autorun.java @@ -0,0 +1,47 @@ +package baritone.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import baritone.util.Out; +import net.minecraft.client.main.Main; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +/** + * + * @author avecowa + */ +public class Autorun { + public static void start(String[] args) { + Out.log(Arrays.asList(args)); + Out.log(System.getProperty("java.library.path")); + //System.setProperty("java.library.path", System.getProperty("user.home") + "/Dropbox/Baritone/mcp918/jars/versions/1.8.8/1.8.8-natives/"); + //Out.log(System.getProperty("java.library.path")); + Main.main(concat(new String[]{"--version", "mcp", "--accessToken", "0", "--assetsDir", "assets", "--assetIndex", "1.8", "--userProperties", "{}"}, args)); + } + public static void runprocess(String s) throws IOException { + Process p; + Out.log(p = Runtime.getRuntime().exec(s)); + InputStream i = p.getInputStream(); + InputStream e = p.getErrorStream(); + OutputStream o = p.getOutputStream(); + while (p.isAlive() || e.available() > 0 || i.available() > 0) { + while (i.available() > 0) { + System.out.print((char) (i.read())); + } + while (e.available() > 0) { + System.out.print((char) (e.read())); + } + } + } + public static T[] concat(T[] first, T[] second) { + T[] result = Arrays.copyOf(first, first.length + second.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } +} diff --git a/util/BlockPuncher.java b/util/BlockPuncher.java new file mode 100644 index 00000000..885b86c1 --- /dev/null +++ b/util/BlockPuncher.java @@ -0,0 +1,48 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import java.util.ArrayList; +import java.util.Arrays; +import baritone.Baritone; +import baritone.pathfinding.goals.Goal; +import baritone.pathfinding.goals.GoalComposite; +import baritone.pathfinding.goals.GoalTwoBlocks; +import baritone.util.Out; +import net.minecraft.util.math.BlockPos; + +/** + * yeah so just like go and punch this type of block + * + * @author avecowa + * @author leijurv + * + * =P + */ +public class BlockPuncher { + public static boolean setGoalTo(String... block) { + ArrayList closest = Memory.closest(10, block); + if (closest == null || closest.isEmpty()) { + Out.gui("NO " + Arrays.asList(block) + " NEARBY. OH MAN", Out.Mode.Standard); + return false; + } + Goal[] goals = new Goal[closest.size()]; + for (int i = 0; i < goals.length; i++) { + goals[i] = new GoalTwoBlocks(closest.get(i)); + } + Baritone.goal = new GoalComposite(goals); + return true; + } + public static boolean tick(String... block) { + if (!setGoalTo(block)) { + return false; + } + if (Baritone.currentPath == null && !Baritone.isThereAnythingInProgress) { + Baritone.findPathInNewThread(false); + } + return true; + } +} diff --git a/util/ChatCommand.java b/util/ChatCommand.java new file mode 100644 index 00000000..48363f36 --- /dev/null +++ b/util/ChatCommand.java @@ -0,0 +1,436 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import baritone.inventory.AnotherStealer; +import baritone.schematic.SchematicBuilder; +import baritone.schematic.Schematic; +import baritone.schematic.SchematicLoader; +import baritone.inventory.SmeltingTask; +import baritone.inventory.CraftingTask; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Random; +import baritone.movement.Combat; +import baritone.strategy.EarlyGameStrategy; +import baritone.ui.LookManager; +import baritone.Baritone; +import baritone.movement.Parkour; +import baritone.mining.MickeyMine; +import baritone.pathfinding.goals.GoalBlock; +import baritone.pathfinding.goals.GoalGetToBlock; +import baritone.pathfinding.goals.GoalXZ; +import baritone.pathfinding.goals.GoalYLevel; +import baritone.ui.AimBow; +import baritone.ui.Screenshot; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author avecowa + */ +public class ChatCommand { + private static WorldClient theWorld() { + return Minecraft.getMinecraft().world; + } + private static EntityPlayerSP thePlayer() { + return Minecraft.getMinecraft().player; + } + private static ArrayList fields; + private static ArrayList methods; + private static Method DONTYOUDARE; + static { + DONTYOUDARE = null; +// try { +// DONTYOUDARE = ChatCommand.class.getMethod("message", String.class); +// } catch (NoSuchMethodException ex) { +// Logger.getLogger(ChatCommand.class.getName()).log(Level.SEVERE, null, ex); +// } catch (SecurityException ex) { +// Logger.getLogger(ChatCommand.class.getName()).log(Level.SEVERE, null, ex); +// } + methods = new ArrayList(); + fields = new ArrayList(); + addMethods(ChatCommand.class); + addMethods(MCEdit.class); + addFields(Baritone.class); + addFields(Combat.class); + addFields(SmeltingTask.class); + addFields(LookManager.class); + } + public static void addFields(Class c) { + Field[] temp = c.getFields(); + for (Field f : temp) { + if (f.getType().equals(boolean.class) && Modifier.isPublic(f.getModifiers()) && Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers())) { + fields.add(f); + } + } + } + public static void addMethods(Class c) { + Method[] temp = c.getDeclaredMethods(); + for (Method m : temp) { + if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(String.class) && m.getReturnType().equals(String.class) && !m.equals(DONTYOUDARE)) { + methods.add(m); + } + } + } + public static boolean message(String message) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Out.log("MSG: " + message); + String text = (message.charAt(0) == '/' ? message.substring(1) : message).trim(); + String command = text.split(" ")[0]; + for (Method method : methods) { + if (method.getName().equalsIgnoreCase(command)) { + message = (String) method.invoke(null, text); + Out.gui(message, Out.Mode.Minimal); + return true; + } + } + int argc = text.split(" ").length; + for (Field field : fields) { + if (field.getName().equalsIgnoreCase(command)) { + boolean value = argc == 1 ? !field.getBoolean(null) : Boolean.parseBoolean(text.split(" ")[2]); + field.setBoolean(null, value); + Out.gui(command + " is now " + value, Out.Mode.Minimal); + return true; + } + } + return false; + } + public static String set(String message) throws IllegalArgumentException, IllegalAccessException { + int argc = message.split(" ").length; + if (argc <= 1) { + return "Arguments plz"; + } + String item = message.split(" ")[1]; + for (Field field : fields) { + if (field.getName().equalsIgnoreCase(item)) { + boolean value; + if (argc == 2) { + value = !field.getBoolean(null); + } else { + value = Boolean.parseBoolean(message.split(" ")[2]); + } + field.setBoolean(null, value); + return item + " is now " + value; + } + } + return "THATS NOT A THING"; + } + public static String importfrom(String message) throws ClassNotFoundException { + String[] args = message.split(" "); + if (args.length != 3 || (!"m".equals(args[1]) && !"f".equals(args[1]))) { + return "import (m/f) class"; + } + Class c = Class.forName(args[2]); + if (args[1].equals("m")) { + addMethods(c); + } else { + addFields(c); + } + return "Added from " + c; + } + public static String death(String message) { + Baritone.goal = new GoalBlock(Baritone.death); + return "Set goal to " + Baritone.goal; + } + public static String craft(String message) { + String spec = message.substring(5).trim(); + if (spec.length() > 0) { + String item = spec.split(" ")[0]; + String amt = spec.split(" ")[1]; + ItemStack stack = new ItemStack(Item.getByNameOrId(item), Integer.parseInt(amt)); + Out.log(CraftingTask.findOrCreateCraftingTask(stack)); + } + return "k"; + } + public static String smelt(String message) { + String spec = message.substring(5).trim(); + if (spec.length() > 0) { + String item = spec.split(" ")[0]; + String amt = spec.split(" ")[1]; + ItemStack stack = new ItemStack(Item.getByNameOrId(item), Integer.parseInt(amt)); + new SmeltingTask(stack).begin(); + } else { + new SmeltingTask(Minecraft.getMinecraft().player.getCurrentEquippedItem()).begin(); + } + return "k"; + } + public static String containeritem(String message) { + CraftingTask.getRecipeFromItem(thePlayer().getCurrentEquippedItem().getItem()); + return "k"; + } + public static String ore(String message) { + MickeyMine.toggleOre(message.substring(3).trim()); + return ""; + } + public static String parkour(String message) { + return "Parkour: " + Manager.toggle(Parkour.class); + } + public static String mine(String message) { + return "Mreow mine: " + Manager.toggle(MickeyMine.class); + } + public static String fullauto(String message) { + return "Full Auto: " + Manager.toggle(EarlyGameStrategy.class); + } + public static String record(String message) { + return "Record: " + Manager.toggle(Screenshot.class); + } + public static String wizard(String message) { + return "YOURE A LIZARD HARRY " + (Baritone.isThereAnythingInProgress ^= true); + } + public static String actuallyTalk(String message) { + Baritone.actuallyPutMessagesInChat ^= true; + return "toggled to " + Baritone.actuallyPutMessagesInChat; + } + public static String allowPlaceOrBreak(String message) { + return adventure(message); + } + public static String arrowPearl(String message) { + if (AimBow.lastBlock != null) { + Baritone.goal = new GoalXZ(AimBow.lastBlock.getX(), AimBow.lastBlock.getZ()); + Baritone.findPathInNewThread(false); + return "Aiming: Pathing to X" + AimBow.lastBlock.getX() + ", Z" + AimBow.lastBlock.getZ(); + } else { + return "Aiming: You need to be holding a bow!"; + } + } + public static String adventure(String message) { + return "allowBreakOrPlace: " + (Baritone.allowBreakOrPlace ^= true); + } + public static String steal(String message) { + return stealer(message); + } + public static String save(String message) { + String t = message.substring(4).trim(); + if (Baritone.goal == null) { + return "no goal to save"; + } + if (!(Baritone.goal instanceof GoalBlock)) { + return "sorry, goal has to be instanceof GoalBlock"; + } + Memory.goalMemory.put(t, ((GoalBlock) Baritone.goal).pos()); + return "Saved " + Baritone.goal + " under " + t; + } + public static String load(String message) { + return "Set goal to " + (Baritone.goal = new GoalBlock(Memory.goalMemory.get(message.substring(4).trim()))); + } + public static String random(String message) { + double dist = Double.parseDouble(message.substring("random direction".length()).trim()); + double ang = new Random().nextDouble() * Math.PI * 2; + Out.gui("Angle: " + ang, Out.Mode.Debug); + BlockPos playerFeet = new BlockPos(thePlayer().posX, thePlayer().posY, thePlayer().posZ); + int x = playerFeet.getX() + (int) (Math.sin(ang) * dist); + int z = playerFeet.getZ() + (int) (Math.cos(ang) * dist); + Baritone.goal = new GoalXZ(x, z); + return "Set goal to " + Baritone.goal; + } + public static String findgo(String message) { + return Memory.findGoCommand(message.substring(6).trim()); + } + public static String find(String message) { + return Memory.findCommand(message.substring(4).trim()); + } + public static String look(String message) { + LookManager.lookAtBlock(new BlockPos(0, 0, 0), true); + return ""; + } + public static String cancel(String message) { + Baritone.cancelPath(); + Combat.mobHunting = false; + Combat.mobKilling = false; + Baritone.plsCancel = true; + for (Class c : Baritone.managers) { + Manager.cancel(c); + } + return Baritone.isThereAnythingInProgress ? "Cancelled it, but btw I'm pathfinding right now" : "Cancelled it"; + } + public static String cancelfurnace(String message) { + SmeltingTask.clearInProgress(); + return "k =)"; + } + public static String st(String message) { + WorldClient theWorld = theWorld(); + EntityPlayerSP thePlayer = thePlayer(); + BlockPos playerFeet = new BlockPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + Out.gui(Baritone.info(playerFeet), Out.Mode.Minimal); + Out.gui(Baritone.info(playerFeet.down()), Out.Mode.Minimal); + Out.gui(Baritone.info(playerFeet.up()), Out.Mode.Minimal); + return ""; + } + public static String setgoal(String message) { + return goal(message); + } + public static String goal(String message) { + Baritone.plsCancel = false; + int ind = message.indexOf(' ') + 1; + if (ind == 0) { + Baritone.goal = new GoalBlock(thePlayer().playerFeet()); + return "Set goal to " + Baritone.goal; + } + String[] strs = message.substring(ind).split(" "); + int[] coords = new int[strs.length]; + for (int i = 0; i < strs.length; i++) { + try { + coords[i] = Integer.parseInt(strs[i]); + } catch (NumberFormatException nfe) { + Baritone.goal = new GoalBlock(); + return strs[i] + ". yup. A+ coordinate";//A+? you might even say A* + } + } + switch (strs.length) { + case 3: + Baritone.goal = new GoalBlock(coords[0], coords[1], coords[2]); + break; + case 2: + Baritone.goal = new GoalXZ(coords[0], coords[1]); + break; + case 1: + Baritone.goal = new GoalYLevel(coords[0]); + break; + default: + Baritone.goal = new GoalBlock(); + if (strs.length != 0) { + return strs.length + " coordinates. Nice."; + } + break; + } + return "Set goal to " + Baritone.goal; + } + public static String gotoblock(String message) { + return Memory.gotoCommand(message.substring(4).trim().toLowerCase()); + } + public static String kill(String message) { + return Combat.killCommand(message.substring(4).trim().toLowerCase()); + } + public static String player(String message) { + return Memory.playerCommand(message.substring(6).trim()); + } + public static String thisway(String message) { + return "Set goal to " + (Baritone.goal = LookManager.fromAngleAndDirection(Double.parseDouble(message.substring(7).trim()))); + } + public static String path(String message) { + Baritone.plsCancel = false; + String[] split = message.split(" "); + Baritone.findPathInNewThread(thePlayer().playerFeet(), split.length > 1 ? Boolean.parseBoolean(split[1]) : true); + return ""; + } + public static String hardness(String message) { + BlockPos bp = Baritone.whatAreYouLookingAt(); + return bp == null ? "0" : (1 / theWorld().getBlockState(bp).getBlock().getPlayerRelativeBlockHardness(thePlayer(), theWorld(), Baritone.whatAreYouLookingAt())) + ""; + } + public static String info(String message) { + return Baritone.info(Baritone.whatAreYouLookingAt()); + } + public static String toggle(String message) throws IllegalArgumentException, IllegalAccessException { + return set(message); + } + public static String stealer(String message) { + return "stealer: " + Manager.toggle(AnotherStealer.class); + } + public static String printtag(String message) throws IOException { + Schematic sch = SchematicLoader.getLoader().loadFromFile(new File("/Users/galdara/Downloads/schematics/Bakery.schematic")); + Baritone.currentBuilder = new SchematicBuilder(sch, Minecraft.getMinecraft().player.getPosition0()); + return "printed schematic to console."; + } + public static String samplebuild(String message) { + int size = 5; + BlockPos pl = Minecraft.getMinecraft().player.getPosition0(); + BlockPos center = new BlockPos(pl.getX() - size / 2, pl.getY(), pl.getZ()); + Baritone.currentBuilder = new SchematicBuilder(new Schematic(Block.getBlockFromName("dirt"), size), center); + return "ok"; + } + public static String pinwheel(String message) { + if (true) { + return "haha. no."; + } + int size = 5; + BlockPos pl = Minecraft.getMinecraft().player.getPosition0(); + BlockPos center = new BlockPos(pl.getX() - size, pl.getY(), pl.getZ() - size); + Baritone.currentBuilder = new SchematicBuilder(new Schematic(Block.getBlockFromName("dirt"), size * 2 + 1, false, true), center); + return "ok"; + } + public static String getToGoal(String message) { + Baritone.plsCancel = false; + int ind = message.indexOf(' ') + 1; + if (ind == 0) { + Baritone.goal = new GoalGetToBlock(thePlayer().playerFeet()); + return "Set goal to " + Baritone.goal; + } + String[] strs = message.substring(ind).split(" "); + int[] coords = new int[strs.length]; + for (int i = 0; i < strs.length; i++) { + try { + coords[i] = Integer.parseInt(strs[i]); + } catch (NumberFormatException nfe) { + Baritone.goal = new GoalGetToBlock(); + return strs[i] + ". yup. A+ coordinate";//A+? you might even say A* + } + } + switch (strs.length) { + case 3: + Baritone.goal = new GoalGetToBlock(new BlockPos(coords[0], coords[1], coords[2])); + break; + default: + Baritone.goal = new GoalGetToBlock(); + if (strs.length != 0) { + return strs.length + " coordinates. Nice."; + } + break; + } + return "Set goal to " + Baritone.goal; + } + public static String debug(String message) { + Out.mode = Out.Mode.Debug; + return "Set mode to debug"; + } + public static String chatMode(String message) { + String[] args = message.split(" "); + if (args.length == 1) { + return "To what..."; + } + String arg = args[1].toLowerCase(); + switch (arg) { + case "none": + case "1": + Out.mode = Out.Mode.None; + break; + case "minimal": + case "2": + Out.mode = Out.Mode.Minimal; + break; + case "standard": + case "3": + Out.mode = Out.Mode.Standard; + break; + case "debug": + case "4": + Out.mode = Out.Mode.Debug; + break; + case "ludicrous": + case "5": + Out.mode = Out.Mode.Ludicrous; + break; + default: + return "That is note a valid mode"; + } + return "ok"; + } +// public static String testcode(String message) { +// Out.mode = Out.Mode.Debug; +// Out.gui("Testing", Out.Mode.Debug); +// return "OK"; +// } +} diff --git a/util/FakeArrow.java b/util/FakeArrow.java new file mode 100644 index 00000000..b4285c6e --- /dev/null +++ b/util/FakeArrow.java @@ -0,0 +1,343 @@ +package baritone.util; + +import java.util.List; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.IProjectile; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class FakeArrow extends Entity implements IProjectile { + private int xTile = -1; + private int yTile = -1; + private int zTile = -1; + private Block inTile; + private int inData; + private boolean inGround; + /** + * 1 if the player can pick up the arrow + */ + public int canBePickedUp; + /** + * Seems to be some sort of timer for animating an arrow. + */ + public int arrowShake; + /** + * The owner of this arrow. + */ + public Entity shootingEntity; + public boolean didIHitAnEntity = false; + private int ticksInGround; + private int ticksInAir; + private double damage = 2.0D; + /** + * The amount of knockback an arrow applies when it hits a mob. + */ + private int knockbackStrength; + public FakeArrow(World worldIn, EntityLivingBase shooter, float velocity, float partialTucks) { + super(worldIn); + double d0 = shooter.lastTickPosX + (shooter.posX - shooter.lastTickPosX) * (double) partialTucks; + double d1 = shooter.lastTickPosY + (shooter.posY - shooter.lastTickPosY) * (double) partialTucks; + double d2 = shooter.lastTickPosZ + (shooter.posZ - shooter.lastTickPosZ) * (double) partialTucks; + this.renderDistanceWeight = 10.0D; + this.shootingEntity = shooter; + if (shooter instanceof EntityPlayer) { + this.canBePickedUp = 1; + } + this.setSize(0.5F, 0.5F); + this.setLocationAndAngles(d0, d1 + (double) shooter.getEyeHeight(), d2, shooter.rotationYaw, shooter.rotationPitch); + this.posX -= (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F); + this.posY -= 0.10000000149011612D; + this.posZ -= (double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F); + this.setPosition(this.posX, this.posY, this.posZ); + this.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI)); + this.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI)); + this.motionY = (double) (-MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI)); + this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, velocity * 1.5F, 1.0F); + } + protected void entityInit() { + this.dataWatcher.addObject(16, Byte.valueOf((byte) 0)); + } + /** + * Similar to setArrowHeading, it's point the throwable entity to a x, y, z + * direction. + */ + public void setThrowableHeading(double x, double y, double z, float velocity, float inaccuracy) { + float f = MathHelper.sqrt_double(x * x + y * y + z * z); + x = x / (double) f; + y = y / (double) f; + z = z / (double) f; + //x = x + this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double) inaccuracy; + //y = y + this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double) inaccuracy; + //z = z + this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double) inaccuracy; + x = x * (double) velocity; + y = y * (double) velocity; + z = z * (double) velocity; + this.motionX = x; + this.motionY = y; + this.motionZ = z; + float f1 = MathHelper.sqrt_double(x * x + z * z); + this.prevRotationYaw = this.rotationYaw = (float) (MathHelper.func_181159_b(x, z) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch = (float) (MathHelper.func_181159_b(y, (double) f1) * 180.0D / Math.PI); + this.ticksInGround = 0; + } + public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean p_180426_10_) { + this.setPosition(x, y, z); + this.setRotation(yaw, pitch); + } + /** + * Sets the velocity to the args. Args: x, y, z + */ + public void setVelocity(double x, double y, double z) { + this.motionX = x; + this.motionY = y; + this.motionZ = z; + if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) { + float f = MathHelper.sqrt_double(x * x + z * z); + this.prevRotationYaw = this.rotationYaw = (float) (MathHelper.func_181159_b(x, z) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch = (float) (MathHelper.func_181159_b(y, (double) f) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch; + this.prevRotationYaw = this.rotationYaw; + this.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch); + this.ticksInGround = 0; + } + } + /** + * Called to update the entity's position/logic. + */ + public void onUpdate() { + super.onUpdate(); + if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) { + float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); + this.prevRotationYaw = this.rotationYaw = (float) (MathHelper.func_181159_b(this.motionX, this.motionZ) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch = (float) (MathHelper.func_181159_b(this.motionY, (double) f) * 180.0D / Math.PI); + } + BlockPos blockpos = new BlockPos(this.xTile, this.yTile, this.zTile); + IBlockState iblockstate = this.worldObj.getBlockState(blockpos); + Block block = iblockstate.getBlock(); + if (block.getMaterial() != Material.air) { + block.setBlockBoundsBasedOnState(this.worldObj, blockpos); + AxisAlignedBB axisalignedbb = block.getCollisionBoundingBox(this.worldObj, blockpos, iblockstate); + if (axisalignedbb != null && axisalignedbb.isVecInside(new Vec3(this.posX, this.posY, this.posZ))) { + this.inGround = true; + } + } + if (this.arrowShake > 0) { + --this.arrowShake; + } + if (this.inGround) { + int j = block.getMetaFromState(iblockstate); + if (block == this.inTile && j == this.inData) { + ++this.ticksInGround; + if (this.ticksInGround >= 1200) { + this.setDead(); + } + } else { + this.inGround = false; + this.motionX *= (double) (this.rand.nextFloat() * 0.2F); + this.motionY *= (double) (this.rand.nextFloat() * 0.2F); + this.motionZ *= (double) (this.rand.nextFloat() * 0.2F); + this.ticksInGround = 0; + this.ticksInAir = 0; + } + } else { + ++this.ticksInAir; + Vec3 vec31 = new Vec3(this.posX, this.posY, this.posZ); + Vec3 vec3 = new Vec3(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); + MovingObjectPosition movingobjectposition = this.worldObj.rayTraceBlocks(vec31, vec3, false, true, false); + vec31 = new Vec3(this.posX, this.posY, this.posZ); + vec3 = new Vec3(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); + if (movingobjectposition != null) { + vec3 = new Vec3(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord); + } + Entity entity = null; + List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D)); + double d0 = 0.0D; + for (int i = 0; i < list.size(); ++i) { + Entity entity1 = (Entity) list.get(i); + if (entity1.canBeCollidedWith() && (entity1 != this.shootingEntity || this.ticksInAir >= 5)) { + float f1 = 0.3F; + AxisAlignedBB axisalignedbb1 = entity1.getEntityBoundingBox().expand((double) f1, (double) f1, (double) f1); + MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3); + if (movingobjectposition1 != null) { + double d1 = vec31.squareDistanceTo(movingobjectposition1.hitVec); + if (d1 < d0 || d0 == 0.0D) { + entity = entity1; + d0 = d1; + } + } + } + } + if (entity != null) { + movingobjectposition = new MovingObjectPosition(entity); + } + if (movingobjectposition != null && movingobjectposition.entityHit != null && movingobjectposition.entityHit instanceof EntityPlayer) { + EntityPlayer entityplayer = (EntityPlayer) movingobjectposition.entityHit; + if (entityplayer.capabilities.disableDamage || this.shootingEntity instanceof EntityPlayer && !((EntityPlayer) this.shootingEntity).canAttackPlayer(entityplayer)) { + movingobjectposition = null; + } + } + if (movingobjectposition != null) { + if (movingobjectposition.entityHit != null) { + float f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ); + int l = MathHelper.ceiling_double_int((double) f2 * this.damage); + didIHitAnEntity = true; + /*if (this.getIsCritical()) { + l += this.rand.nextInt(l / 2 + 2); + } + mageSource damagesource; + if (this.shootingEntity == null) { + damagesource = DamageSource.causeArrowDamage(this, this); + } else { + damagesource = DamageSource.causeArrowDamage(this, this.shootingEntity); + } + if (this.isBurning() && !(movingobjectposition.entityHit instanceof EntityEnderman)) { + movingobjectposition.entityHit.setFire(5); + } + if (movingobjectposition.entityHit.attackEntityFrom(damagesource, (float) l)) { + if (movingobjectposition.entityHit instanceof EntityLivingBase) { + EntityLivingBase entitylivingbase = (EntityLivingBase) movingobjectposition.entityHit; + if (!this.worldObj.isRemote) { + entitylivingbase.setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1); + } + if (this.knockbackStrength > 0) { + float f7 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); + if (f7 > 0.0F) { + movingobjectposition.entityHit.addVelocity(this.motionX * (double) this.knockbackStrength * 0.6000000238418579D / (double) f7, 0.1D, this.motionZ * (double) this.knockbackStrength * 0.6000000238418579D / (double) f7); + } + } + if (this.shootingEntity instanceof EntityLivingBase) { + EnchantmentHelper.applyThornEnchantments(entitylivingbase, this.shootingEntity); + EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase) this.shootingEntity, entitylivingbase); + } + if (this.shootingEntity != null && movingobjectposition.entityHit != this.shootingEntity && movingobjectposition.entityHit instanceof EntityPlayer && this.shootingEntity instanceof EntityPlayerMP) { + ((EntityPlayerMP) this.shootingEntity).playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F)); + } + } + this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + if (!(movingobjectposition.entityHit instanceof EntityEnderman)) { + this.setDead(); + } + } else { + this.motionX *= -0.10000000149011612D; + this.motionY *= -0.10000000149011612D; + this.motionZ *= -0.10000000149011612D; + this.rotationYaw += 180.0F; + this.prevRotationYaw += 180.0F; + this.ticksInAir = 0; + }*/ + } else { + BlockPos blockpos1 = movingobjectposition.getBlockPos(); + this.xTile = blockpos1.getX(); + this.yTile = blockpos1.getY(); + this.zTile = blockpos1.getZ(); + IBlockState iblockstate1 = this.worldObj.getBlockState(blockpos1); + this.inTile = iblockstate1.getBlock(); + this.inData = this.inTile.getMetaFromState(iblockstate1); + this.motionX = (double) ((float) (movingobjectposition.hitVec.xCoord - this.posX)); + this.motionY = (double) ((float) (movingobjectposition.hitVec.yCoord - this.posY)); + this.motionZ = (double) ((float) (movingobjectposition.hitVec.zCoord - this.posZ)); + float f5 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ); + this.posX -= this.motionX / (double) f5 * 0.05000000074505806D; + this.posY -= this.motionY / (double) f5 * 0.05000000074505806D; + this.posZ -= this.motionZ / (double) f5 * 0.05000000074505806D; + //this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); + this.inGround = true; + this.arrowShake = 7; + if (this.inTile.getMaterial() != Material.air) { + this.inTile.onEntityCollidedWithBlock(this.worldObj, blockpos1, iblockstate1, this); + } + } + } + this.posX += this.motionX; + this.posY += this.motionY; + this.posZ += this.motionZ; + float f3 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); + this.rotationYaw = (float) (MathHelper.func_181159_b(this.motionX, this.motionZ) * 180.0D / Math.PI); + for (this.rotationPitch = (float) (MathHelper.func_181159_b(this.motionY, (double) f3) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) { + ; + } + while (this.rotationPitch - this.prevRotationPitch >= 180.0F) { + this.prevRotationPitch += 360.0F; + } + while (this.rotationYaw - this.prevRotationYaw < -180.0F) { + this.prevRotationYaw -= 360.0F; + } + while (this.rotationYaw - this.prevRotationYaw >= 180.0F) { + this.prevRotationYaw += 360.0F; + } + this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F; + this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F; + float f4 = 0.99F; + float f6 = 0.05F; + if (this.isInWater()) { + for (int i1 = 0; i1 < 4; ++i1) { + float f8 = 0.25F; + this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX - this.motionX * (double) f8, this.posY - this.motionY * (double) f8, this.posZ - this.motionZ * (double) f8, this.motionX, this.motionY, this.motionZ, new int[0]); + } + f4 = 0.6F; + } + if (this.isWet()) { + this.extinguish(); + } + this.motionX *= (double) f4; + this.motionY *= (double) f4; + this.motionZ *= (double) f4; + this.motionY -= (double) f6; + this.setPosition(this.posX, this.posY, this.posZ); + this.doBlockCollisions(); + } + } + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + public void writeEntityToNBT(NBTTagCompound tagCompound) { + tagCompound.setShort("xTile", (short) this.xTile); + tagCompound.setShort("yTile", (short) this.yTile); + tagCompound.setShort("zTile", (short) this.zTile); + tagCompound.setShort("life", (short) this.ticksInGround); + ResourceLocation resourcelocation = (ResourceLocation) Block.blockRegistry.getNameForObject(this.inTile); + tagCompound.setString("inTile", resourcelocation == null ? "" : resourcelocation.toString()); + tagCompound.setByte("inData", (byte) this.inData); + tagCompound.setByte("shake", (byte) this.arrowShake); + tagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0)); + tagCompound.setByte("pickup", (byte) this.canBePickedUp); + tagCompound.setDouble("damage", this.damage); + } + /** + * (abstract) Protected helper method to read subclass entity data from NBT. + */ + public void readEntityFromNBT(NBTTagCompound tagCompund) { + this.xTile = tagCompund.getShort("xTile"); + this.yTile = tagCompund.getShort("yTile"); + this.zTile = tagCompund.getShort("zTile"); + this.ticksInGround = tagCompund.getShort("life"); + if (tagCompund.hasKey("inTile", 8)) { + this.inTile = Block.getBlockFromName(tagCompund.getString("inTile")); + } else { + this.inTile = Block.getBlockById(tagCompund.getByte("inTile") & 255); + } + this.inData = tagCompund.getByte("inData") & 255; + this.arrowShake = tagCompund.getByte("shake") & 255; + this.inGround = tagCompund.getByte("inGround") == 1; + if (tagCompund.hasKey("damage", 99)) { + this.damage = tagCompund.getDouble("damage"); + } + if (tagCompund.hasKey("pickup", 99)) { + this.canBePickedUp = tagCompund.getByte("pickup"); + } else if (tagCompund.hasKey("player", 99)) { + this.canBePickedUp = tagCompund.getBoolean("player") ? 1 : 0; + } + } +} diff --git a/util/MCEdit.java b/util/MCEdit.java new file mode 100644 index 00000000..530701a5 --- /dev/null +++ b/util/MCEdit.java @@ -0,0 +1,69 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import java.util.HashSet; +import baritone.Baritone; +import baritone.pathfinding.goals.GoalComposite; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author leijurv + */ +public class MCEdit extends Manager { + static BlockPos pos1 = null; + static BlockPos pos2 = null; + public static String pos1(String s) { + return "Pos 1: " + (pos1 = Minecraft.getMinecraft().player.getPosition0()); + } + public static String pos2(String s) { + return "Pos 2: " + (pos2 = Minecraft.getMinecraft().player.getPosition0()); + } + public static String delete(String s) { + Manager.getManager(MCEdit.class).toggle(); + return "k"; + } + private static HashSet toBreak() { + HashSet toBreak = new HashSet<>(); + for (int x = Math.min(pos1.getX(), pos2.getX()); x <= Math.max(pos1.getX(), pos2.getX()); x++) { + for (int y = Math.max(pos1.getY(), pos2.getY()); y >= Math.min(pos1.getY(), pos2.getY()); y--) { + for (int z = Math.min(pos1.getZ(), pos2.getZ()); z <= Math.max(pos1.getZ(), pos2.getZ()); z++) { + BlockPos po = new BlockPos(x, y, z); + Block b = Minecraft.getMinecraft().world.getBlockState(po).getBlock(); + if (!Blocks.air.equals(b)) { + toBreak.add(po); + if (toBreak.size() > 20) { + return toBreak; + } + } + } + } + } + return toBreak; + } + @Override + protected void onTick() { + HashSet toBreak = toBreak(); + if (!toBreak.isEmpty()) { + Baritone.goal = new GoalComposite(toBreak); + if (Baritone.currentPath == null && !Baritone.isThereAnythingInProgress) { + Baritone.findPathInNewThread(false); + } + } + } + @Override + protected void onCancel() { + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + @Override + protected void onStart() { + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } +} diff --git a/util/Manager.java b/util/Manager.java new file mode 100644 index 00000000..8d1ef05f --- /dev/null +++ b/util/Manager.java @@ -0,0 +1,114 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author avecowa + */ +public abstract class Manager { + private boolean enabled = false; + private static HashMap, Manager> managers = new HashMap, Manager>(); + public final static Manager getManager(Class c) { + if (managers.get(c) == null) { + try { + managers.put(c, (Manager) c.getMethod("createInstance", Class.class).invoke(null, c)); + } catch (NoSuchMethodException ex) { + Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex); + managers.put(c, createInstance(c)); + } catch (SecurityException ex) { + Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(Manager.class.getName()).log(Level.SEVERE, null, ex); + } + } + if (managers.get(c) == null) { + throw new RuntimeException("Wtf idek"); + } + return managers.get(c); + } + public final static void tick(Class c) { + getManager(c).tick(); + } + public final static void tick(Class c, boolean prepost) { + getManager(c).tick(prepost); + } + public final static boolean enabled(Class c) { + return getManager(c).enabled(); + } + public final static void cancel(Class c) { + getManager(c).cancel(); + } + public final static void start(Class c) { + getManager(c).start(); + } + public final static boolean toggle(Class c) { + return getManager(c).toggle(); + } + public static Manager createInstance(Class c) { + try { + return (Manager) c.newInstance(); + } catch (InstantiationException ex) { + throw new RuntimeException(ex); + } catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + public final void tick() { + this.tick((Boolean) null); + } + public final void tick(Boolean prepost) { + //Out.log(this + " " + enabled()); + if (!enabled()) { + return; + } + if (prepost == null) { + onTick(); + } else if (prepost) { + onTickPre(); + } else { + onTickPost(); + } + } + public final boolean enabled() { + return onEnabled(enabled); + } + public final void cancel() { + enabled = false; + onCancel(); + } + public final void start() { + enabled = true; + onStart(); + } + public final boolean toggle() { + if (enabled()) { + cancel(); + } else { + start(); + } + return enabled(); + } + protected void onTickPre() { + } + protected void onTickPost() { + } + protected boolean onEnabled(boolean enabled) { + return enabled; + } + protected abstract void onTick(); + protected abstract void onCancel(); + protected abstract void onStart(); +} diff --git a/util/ManagerTick.java b/util/ManagerTick.java new file mode 100644 index 00000000..f2aebb67 --- /dev/null +++ b/util/ManagerTick.java @@ -0,0 +1,23 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +/** + * + * @author avecowa + */ +public abstract class ManagerTick extends Manager { + public static boolean tickPath = false; + @Override + protected final void onTick() { + if (tickPath) { + if (onTick0()) { + tickPath = false; + } + } + } + protected abstract boolean onTick0(); +} diff --git a/util/Memory.java b/util/Memory.java new file mode 100644 index 00000000..d24ec94d --- /dev/null +++ b/util/Memory.java @@ -0,0 +1,402 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; +import baritone.Baritone; +import static baritone.Baritone.findPathInNewThread; +import static baritone.Baritone.goal; +import baritone.pathfinding.goals.GoalBlock; +import baritone.pathfinding.goals.GoalTwoBlocks; +import baritone.util.Manager; +import baritone.util.Out; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.EmptyChunk; + +/** + * + * @author leijurv + */ +public class Memory extends Manager { + public static HashMap blockMemory = new HashMap(); + public static HashMap playerLocationMemory = new HashMap(); + public static HashMap goalMemory = new HashMap(); + public static ArrayList playersCurrentlyInRange = new ArrayList(); + public static Thread scanThread = null; + public static Block air = null; + public Memory() { + } + @Override + protected void onCancel() { + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + @Override + protected void onStart() { + //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + @Override + protected boolean onEnabled(boolean enabled) { + return true; + } + + public static class BlockMemory { + final Block block; + final ArrayList knownPositions;//idk whether to use hashset or arraylist here... + private volatile double furthest; + public BlockMemory(Block block) { + this.block = block; + this.knownPositions = new ArrayList(); + } + public void checkForChange() { + for (BlockPos pos : new ArrayList(knownPositions)) {//make duplicate to prevent concurrent modification exceptions + boolean loaded = blockLoaded(pos); + if (!loaded) { + //Out.gui("Too far away from " + pos + " to remember that it's " + block, true); + } + Block current = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + if (!current.equals(block) || !loaded) { + //Out.gui("Block at " + pos + " has changed from " + block + " to " + current + ". Removing from memory.", true); + knownPositions.remove(pos); + if (loaded) { + scanBlock(pos);//rescan to put in proper memory + } + } + } + } + public void put(BlockPos pos) { + if (knownPositions.size() < 100) { + knownPositions.add(pos); + double dist = distSq(pos); + if (dist > furthest) { + furthest = dist; + return; + } + } + double dist = distSq(pos); + if (dist < furthest) { + knownPositions.add(pos); + knownPositions.remove(furthest()); + recalcFurthest(); + } + } + public BlockPos getOne() { + for (BlockPos pos : knownPositions) { + return pos; + } + return null; + } + public BlockPos closest() { + BlockPos best = null; + double dist = Double.MAX_VALUE; + for (BlockPos pos : knownPositions) { + if (!blockLoaded(pos)) { + continue; + } + if (!block.equals(Minecraft.getMinecraft().world.getBlockState(pos).getBlock())) { + continue; + } + double d = distSq(pos); + if (best == null || d < dist) { + dist = d; + best = pos; + } + } + return best; + } + public void recalcFurthest() { + double dist = Double.MIN_VALUE; + for (BlockPos pos : knownPositions) { + double d = distSq(pos); + if (d > dist) { + dist = d; + } + } + furthest = dist; + } + public BlockPos furthest() { + BlockPos best = null; + double dist = Double.MIN_VALUE; + for (BlockPos pos : knownPositions) { + double d = distSq(pos); + if (best == null || d > dist) { + dist = d; + best = pos; + } + } + return best; + } + } + public static double distSq(BlockPos pos) { + EntityPlayerSP player = Minecraft.getMinecraft().player; + double diffX = player.posX - (pos.getX() + 0.5D); + double diffY = (player.posY + 1.62) - (pos.getY() + 0.5D); + double diffZ = player.posZ - (pos.getZ() + 0.5D); + return diffX * diffX + diffY * diffY + diffZ * diffZ; + } + @Override + public void onTick() { + if (air == null) { + air = Block.getBlockById(0); + } + playersCurrentlyInRange.clear(); + for (EntityPlayer pl : Minecraft.getMinecraft().world.playerEntities) { + String blah = pl.getName().trim().toLowerCase(); + playerLocationMemory.put(blah, new BlockPos(pl.posX, pl.posY, pl.posZ)); + playersCurrentlyInRange.add(blah); + } + if (scanThread == null) { + scanThread = new Thread() { + @Override + public void run() { + try { + run1(); + } catch (Exception ex) { + Logger.getLogger(Memory.class.getName()).log(Level.SEVERE, null, ex); + } + scanThread = null; + } + public void run1() { + Out.gui("Starting passive block scan thread", Out.Mode.Debug); + try { + Thread.sleep(2000); + } catch (InterruptedException ex) { + Logger.getLogger(Memory.class.getName()).log(Level.SEVERE, null, ex); + return; + } + while (true) { + if (Minecraft.getMinecraft() != null && Minecraft.getMinecraft().player != null && Minecraft.getMinecraft().world != null) { + //Out.gui("Beginning passive block scan", true); + long start = System.currentTimeMillis(); + scan(); + long end = System.currentTimeMillis(); + //Out.gui("Passive block scan over after " + (end - start) + "ms", true); + } + try { + Thread.sleep(10000); + } catch (InterruptedException ex) { + Logger.getLogger(Memory.class.getName()).log(Level.SEVERE, null, ex); + return; + } + } + } + }; + scanThread.start(); + } + } + public static String findCommand(String block) { + String lower = block.toLowerCase(); + Out.log(lower); + BlockPos best = null; + double d = Double.MAX_VALUE; + for (Block type : blockMemory.keySet()) { + //Out.log("Considering " + type); + if (type.toString().toLowerCase().contains(lower)) { + BlockPos pos = blockMemory.get(type).closest(); + Out.log("find" + type + " " + pos); + if (pos != null) { + double dist = distSq(pos); + if (best == null || dist < d) { + d = dist; + best = pos; + } + } + } + } + if (best != null) { + return block + " at " + best; + } + return "none"; + } + public static BlockPos closestOne(String... block) { + /*BlockPos best = null; + double d = Double.MAX_VALUE; + for (Block type : blockMemory.keySet()) { + //Out.log("Considering " + type); + for (String b : block) { + String lower = "block{minecraft:" + b.toLowerCase() + "}"; + if (type.toString().toLowerCase().equals(lower)) { + BlockPos pos = blockMemory.get(type).closest(); + Out.log("closest" + type + " " + pos); + if (pos != null) { + double dist = distSq(pos); + if (best == null || dist < d) { + d = dist; + best = pos; + } + } + } + } + } + return best;*/ + ArrayList u = closest(1, block); + if (u.isEmpty()) { + return null; + } + return u.get(0); + } + public static ArrayList closest(int num, String... block) { + ArrayList result = new ArrayList(); + for (Block type : blockMemory.keySet()) { + //Out.log("Considering " + type); + for (String b : block) { + String lower = "block{minecraft:" + b.toLowerCase() + "}"; + if (type.toString().toLowerCase().equals(lower)) { + for (BlockPos pos : blockMemory.get(type).knownPositions) { + if (type.equals(Minecraft.getMinecraft().world.getBlockState(pos).getBlock()) && !result.contains(pos)) { + if (b.equals("stone")) { + if (!type.getItemDropped(Minecraft.getMinecraft().world.getBlockState(pos), new Random(), 0).equals(Item.getByNameOrId("cobblestone"))) { + continue; + } + } + result.add(pos); + } + } + } + } + } + result.sort(new Comparator() { + @Override + public int compare(BlockPos o1, BlockPos o2) { + return Double.compare(distSq(o1), distSq(o2)); + } + }); + return new ArrayList(result.subList(0, Math.min(num, result.size()))); + } + public static String findGoCommand(String block) { + String lower = block.toLowerCase(); + Out.log(lower); + BlockPos best = null; + double d = Double.MAX_VALUE; + for (Block type : blockMemory.keySet()) { + //Out.log("Considering " + type); + if (type.toString().toLowerCase().contains(lower)) { + BlockPos pos = blockMemory.get(type).closest(); + Out.log("findgo" + type + " " + pos); + if (pos != null) { + double dist = distSq(pos); + if (best == null || dist < d) { + d = dist; + best = pos; + } + } + } + } + if (best != null) { + goal = new GoalTwoBlocks(best); + Baritone.findPathInNewThread(true); + return "Pathing to " + goal + " " + block + " at " + best; + } + return "none"; + } + public static void scan() { + for (Block block : blockMemory.keySet()) { + blockMemory.get(block).checkForChange(); + } + for (Block block : blockMemory.keySet()) { + blockMemory.get(block).recalcFurthest(); + } + BlockPos playerFeet = Minecraft.getMinecraft().player.getPosition0(); + int X = playerFeet.getX(); + int Y = playerFeet.getY(); + int Z = playerFeet.getZ(); + int ymin = Math.max(0, Y - 10); + int ymax = Math.min(Y + 10, 256); + for (int x = X; x >= X - SCAN_DIST && blockLoaded(new BlockPos(x, Y, Z)); x--) { + for (int z = Z; z >= Z - SCAN_DIST && blockLoaded(new BlockPos(x, Y, z)); z--) { + for (int y = ymin; y <= ymax; y++) { + scanBlock(new BlockPos(x, y, z)); + } + } + for (int z = Z; z <= Z + SCAN_DIST && blockLoaded(new BlockPos(x, Y, z)); z++) { + for (int y = ymin; y <= ymax; y++) { + scanBlock(new BlockPos(x, y, z)); + } + } + } + for (int x = X; x <= X + SCAN_DIST && blockLoaded(new BlockPos(x, Y, Z)); x++) { + for (int z = Z; z >= Z - SCAN_DIST && blockLoaded(new BlockPos(x, Y, z)); z--) { + for (int y = ymin; y <= ymax; y++) { + scanBlock(new BlockPos(x, y, z)); + } + } + for (int z = Z; z <= Z + SCAN_DIST && blockLoaded(new BlockPos(x, Y, z)); z++) { + for (int y = ymin; y <= ymax; y++) { + scanBlock(new BlockPos(x, y, z)); + } + } + } + } + public static final int SCAN_DIST = 50; + public static void scanBlock(BlockPos pos) { + Block block = Minecraft.getMinecraft().world.getBlockState(pos).getBlock(); + if (air.equals(block)) { + return; + } + BlockMemory memory = getMemory(block); + memory.put(pos); + } + public static BlockMemory getMemory(Block block) { + BlockMemory cached = blockMemory.get(block); + if (cached != null) { + return cached; + } + BlockMemory n = new BlockMemory(block); + blockMemory.put(block, n); + return n; + } + public static boolean blockLoaded(BlockPos pos) { + return !(Minecraft.getMinecraft().world.getChunkFromBlockCoords(pos) instanceof EmptyChunk); + } + public static String gotoCommand(String targetName) { + for (String name : playerLocationMemory.keySet()) { + if (name.contains(targetName) || targetName.contains(name)) { + Baritone.goal = new GoalBlock(playerLocationMemory.get(name)); + findPathInNewThread(Minecraft.getMinecraft().player.getPosition0(), true); + return "Pathing to " + name + " at " + goal; + } + } + /* + for (EntityPlayer pl : Minecraft.getMinecraft().world.playerEntities) { + String blah = pl.getName().trim().toLowerCase(); + if (blah.contains(name) || name.contains(blah)) { + BlockPos pos = new BlockPos(pl.posX, pl.posY, pl.posZ); + goal = new GoalBlock(pos); + findPathInNewThread(Minecraft.getMinecraft().player.getPosition0(), true); + return "Pathing to " + pl.getName() + " at " + goal; + } + }*/ + return "Couldn't find " + targetName; + } + public static String playerCommand(String targetName) { + String resp = ""; + for (EntityPlayer pl : Minecraft.getMinecraft().world.playerEntities) { + resp += "(" + pl.getName() + "," + pl.posX + "," + pl.posY + "," + pl.posZ + ")\n"; + if (pl.getName().equals(targetName)) { + BlockPos pos = new BlockPos(pl.posX, pl.posY, pl.posZ); + goal = new GoalBlock(pos); + return "Set goal to " + goal; + } + } + for (String x : resp.split("\n")) { + Out.gui(x, Out.Mode.Minimal); + } + if (targetName.equals("")) { + return ""; + } + return "Couldn't find " + targetName; + } +} diff --git a/util/Out.java b/util/Out.java new file mode 100644 index 00000000..ca704ff5 --- /dev/null +++ b/util/Out.java @@ -0,0 +1,123 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; + +/** + * This class serves the purpose of filtering what messages get send to the chat + * and the standard out. + * + * @author avecowa + */ +public class Out { + /** + * Out has an Mode at all times. The Mode determines behavior of of the + * filter. + */ + public static enum Mode { + /** + * This mode signifies that NO messages should be sent to the chat. + */ + None, + /** + * This mode signifies that almost no messages should be sent to the + * chat. The exceptions are mainly outputs of chat commands.Background + * activities should not use this mode. + */ + Minimal, + /** + * This mode signifies that important messages should be sent to the + * chat. Rapidly repeating messages or long messages should not use this + * mode. Generally no more than 1 of these should be called within 4 + * seconds. The expectation is for the user to read everything that is + * of this mode. + */ + Standard, + /** + * This mode signifies that all messages should be sent to the chat. + * This mode should not exclude any messages Additionally, if this is + * set all messages will begin with a file trace: + * "baritone.util.Out:44\tMessage" + */ + Debug, + /** + * This is a dangerous game. All log writes will also be posted to the + * chat. Expect messages to fire at you at about 10 per tick. You may + * not survive. + */ + Ludicrous + } + public static Mode mode = Mode.Standard; + /** + * Logs a message to the standard system output. Before writing it runs a + * stacktrace and appends the class and line number of the calling method to + * the front of the message. + * + * @see Out.Mode.Ludicrous + * @param o This is the object to be printed out. If this is not a String, + * o.toString() will be used. + */ + public static void log(Object o) { + String trace = trace(); + System.out.println(trace + '\t' + o.toString()); + if (mode == Mode.Ludicrous) { + chatRaw("§5[§dLog§5|§2" + trace + "§5]§f " + o.toString()); + } + } + /** + * Prints a message to the client's chat GUI. Messages will not be displayed + * if their Mode is a lower importance than the set mode. + * + * @param o This is the object to be printed out. If this is not a String, + * o.toString() will be used. + * @param req This determines how the filter will treat the message. If a + * message is sent with a Mode.Debug requirement, it will only be printed if + * Out.mode is Debug or Ludicrous. Do not use a Mode.None or a + * Mode.Ludicrous in this parameter. + * @exception IllegalArgumentException This will only be triggered if a + * messages given with a req of Node or Ludicrous + */ + public static void gui(Object o, Mode req) throws IllegalArgumentException { + if (req.equals(Mode.None) || req.equals(Mode.Ludicrous)) { + throw new IllegalArgumentException("You cannot send messages of mode " + req); + } + if (o == null) { + return; + } + String message = o.toString(); + if (message.isEmpty()) { + return; + } + String trace = trace(); + System.out.println(trace + '\t' + message); + if (req.compareTo(mode) <= 0) { + if (Mode.Debug.compareTo(mode) <= 0) { + message = "§5[§dBaritone§5|§2" + trace() + "§5]§f " + message; + } else { + message = "§5[§dBaritone§5]§7 " + message; + } + chatRaw(message); + } + } + private static void chatRaw(String s) { + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(s)); + } + private static String trace() { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + StackTraceElement trace = stack[3]; + boolean a = false; + for (int i = 3; i < stack.length; i++) { + StackTraceElement e = stack[i]; + if (!e.getClassName().equals(Out.class.getName())) { + trace = e; + break; + } + } + return trace.getClassName() + ":" + trace.getLineNumber(); + } +} diff --git a/util/ToolSet.java b/util/ToolSet.java new file mode 100644 index 00000000..cb6cd2b4 --- /dev/null +++ b/util/ToolSet.java @@ -0,0 +1,107 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.util; + +import java.util.ArrayList; +import java.util.HashMap; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; + +/** + * + * @author avecowa + */ +public class ToolSet { + public ArrayList tools; + public ArrayList slots; + public HashMap cache = new HashMap(); + public ToolSet(ArrayList tools, ArrayList slots) { + this.tools = tools; + this.slots = slots; + } + public ToolSet() { + EntityPlayerSP p = Minecraft.getMinecraft().player; + ItemStack[] inv = p.inventory.mainInventory; + tools = new ArrayList(); + slots = new ArrayList(); + //Out.log("inv: " + Arrays.toString(inv)); + boolean fnull = false; + for (byte i = 0; i < 9; i++) { + if (!fnull || (inv[i] != null && inv[i].getItem().isItemTool(null))) { + tools.add(inv[i] != null ? inv[i].getItem() : null); + slots.add(i); + fnull |= inv[i] == null || (!inv[i].getItem().isDamageable()); + } + } + } + public Item getBestTool(Block b) { + if (cache.get(b) != null) { + return tools.get(cache.get(b)); + } + byte best = 0; + //Out.log("best: " + best); + float value = 0; + for (byte i = 0; i < tools.size(); i++) { + Item item = tools.get(i); + if (item == null) { + item = Item.getByNameOrId("minecraft:apple"); + } + //Out.log(inv[i]); + float v = item.getStrVsBlock(new ItemStack(item), b); + //Out.log("v: " + v); + if (v > value) { + value = v; + best = i; + } + } + //Out.log("best: " + best); + cache.put(b, best); + return tools.get(best); + } + public byte getBestSlot(Block b) { + if (cache.get(b) != null) { + return slots.get(cache.get(b)); + } + byte best = 0; + //Out.log("best: " + best); + float value = 0; + for (byte i = 0; i < tools.size(); i++) { + Item item = tools.get(i); + if (item == null) { + item = Item.getByNameOrId("minecraft:apple"); + } + //Out.log(inv[i]); + float v = item.getStrVsBlock(new ItemStack(item), b); + //Out.log("v: " + v); + if (v > value) { + value = v; + best = i; + } + } + //Out.log("best: " + best); + cache.put(b, best); + return slots.get(best); + } + public double getStrVsBlock(Block b, BlockPos pos) { + Item item = this.getBestTool(b); + if (item == null) { + item = Item.getByNameOrId("minecraft:apple"); + } + float f = b.getBlockHardness(Minecraft.getMinecraft().world, pos); + return f < 0.0F ? 0.0F : (!canHarvest(b, item) ? item.getStrVsBlock(new ItemStack(item), b) / f / 100.0F : item.getStrVsBlock(new ItemStack(item), b) / f / 30.0F); + } + public boolean canHarvest(Block blockIn, Item item) { + if (blockIn.getMaterial().isToolNotRequired()) { + return true; + } else { + return new ItemStack(item).canHarvestBlock(blockIn); + } + } +}