diff --git a/src/main/java/baritone/bot/GameEventHandler.java b/src/main/java/baritone/bot/GameEventHandler.java index 011fb601e..3573c6612 100755 --- a/src/main/java/baritone/bot/GameEventHandler.java +++ b/src/main/java/baritone/bot/GameEventHandler.java @@ -4,6 +4,7 @@ import baritone.bot.behavior.Behavior; import baritone.bot.event.IGameEventListener; import baritone.bot.event.events.ChatEvent; import baritone.bot.event.events.ChunkEvent; +import baritone.bot.pathing.action.ActionWorldHelper; import net.minecraft.client.settings.KeyBinding; import org.lwjgl.input.Keyboard; @@ -15,11 +16,15 @@ import java.util.function.Consumer; */ public final class GameEventHandler implements IGameEventListener { - GameEventHandler() {} + GameEventHandler() { + } @Override public final void onTick() { dispatch(behavior -> onTick()); + while (true) { + System.out.println(ActionWorldHelper.lavaFlowing); + } } @Override diff --git a/src/main/java/baritone/bot/behavior/PathExecution.java b/src/main/java/baritone/bot/behavior/PathExecution.java index 00f7d09dd..c205d562c 100644 --- a/src/main/java/baritone/bot/behavior/PathExecution.java +++ b/src/main/java/baritone/bot/behavior/PathExecution.java @@ -1,7 +1,6 @@ package baritone.bot.behavior; import baritone.bot.pathing.calc.IPath; -import baritone.bot.pathing.movements.Movement; import baritone.bot.utils.Helper; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; @@ -25,8 +24,6 @@ public class PathExecution extends Behavior implements Helper { // TODO the old Path used to keep track of the index in the path // and only increment it when the movement said it was done, not when it detected that the player feet had // moved into the next position - Movement movement = path.subsequentMovement(playerFeet); - //movement.tick() } else { Tuple closest = path.closestPathPos(player.posX, player.posY, player.posZ); if (closest.getFirst() > MAX_DIST_FROM_PATH) { diff --git a/src/main/java/baritone/bot/pathing/action/Action.java b/src/main/java/baritone/bot/pathing/action/Action.java index c7c1120b5..95455b068 100644 --- a/src/main/java/baritone/bot/pathing/action/Action.java +++ b/src/main/java/baritone/bot/pathing/action/Action.java @@ -2,14 +2,14 @@ package baritone.bot.pathing.action; import baritone.bot.Baritone; import baritone.bot.event.AbstractGameEventListener; +import baritone.bot.pathing.action.ActionState.ActionStatus; import baritone.bot.utils.Helper; import baritone.bot.utils.Utils; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; -import baritone.bot.pathing.action.ActionState.ActionStatus; import net.minecraft.util.math.Vec3d; -public abstract class Action implements AbstractGameEventListener, Helper { +public abstract class Action implements AbstractGameEventListener, Helper, ActionWorldHelper { protected ActionState currentState; diff --git a/src/main/java/baritone/bot/pathing/action/ActionWorldHelper.java b/src/main/java/baritone/bot/pathing/action/ActionWorldHelper.java new file mode 100644 index 000000000..ee2500239 --- /dev/null +++ b/src/main/java/baritone/bot/pathing/action/ActionWorldHelper.java @@ -0,0 +1,119 @@ +package baritone.bot.pathing.action; + +import baritone.bot.utils.BlockStateInterface; +import net.minecraft.block.*; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +/** + * Static helpers for cost calculation + * + * @author leijurv + */ +public interface ActionWorldHelper { + Block waterFlowing = Block.getBlockById(8); + Block waterStill = Block.getBlockById(9); + Block lavaFlowing = Block.getBlockById(10); + Block lavaStill = Block.getBlockById(11); + + /** + * Is this block water? Includes both still and flowing + * + * @param b + * @return + */ + static boolean isWater(Block b) { + return waterFlowing.equals(b) || waterStill.equals(b); + } + + static boolean isWater(BlockPos bp) { + return isWater(BlockStateInterface.get(bp).getBlock()); + } + + static boolean isLiquid(Block b) { + return b instanceof BlockLiquid; + //return b != null && (waterFlowing.equals(b) || waterStill.equals(b) || lavaFlowing.equals(b) || lavaStill.equals(b)); + } + + static boolean isFlowing(BlockPos pos, IBlockState state) { + Block b = state.getBlock(); + if (b instanceof BlockLiquid) { + System.out.println("Need to fix get flow check!!!"); + //return BlockLiquid.getFlow(Minecraft.getMinecraft().world, pos, state) != -1000.0D; + } + return false; + } + + static boolean isLava(Block b) { + return lavaFlowing.equals(b) || lavaStill.equals(b); + } + + static boolean isLiquid(BlockPos p) { + return isLiquid(BlockStateInterface.get(p).getBlock()); + } + + static boolean avoidBreaking(BlockPos pos) { + Block b = BlockStateInterface.get(pos).getBlock(); + Block below = BlockStateInterface.get(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 + */ + static boolean canWalkThrough(BlockPos pos) { + IBlockState state = BlockStateInterface.get(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); + } + + static boolean avoidWalkingInto(BlockPos pos) { + Block block = BlockStateInterface.get(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 + */ + static boolean canWalkOn(BlockPos pos) { + IBlockState state = BlockStateInterface.get(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 state.isBlockNormalCube() && !isLava(block); + } +} diff --git a/src/main/java/baritone/bot/pathing/calc/IPath.java b/src/main/java/baritone/bot/pathing/calc/IPath.java index 57d6cb016..09fb4493a 100644 --- a/src/main/java/baritone/bot/pathing/calc/IPath.java +++ b/src/main/java/baritone/bot/pathing/calc/IPath.java @@ -1,6 +1,6 @@ package baritone.bot.pathing.calc; -import baritone.bot.pathing.movements.Movement; +import baritone.bot.pathing.action.Action; import baritone.bot.utils.Utils; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; @@ -18,7 +18,7 @@ public interface IPath { * movements.get(i).getDest() should equal positions.get(i+1) * movements.size() should equal positions.size()-1 */ - List movements(); + List actions(); /** * All positions along the way. @@ -32,12 +32,12 @@ public interface IPath { * @param currentPosition the current position * @return */ - default Movement subsequentMovement(BlockPos currentPosition) { + default Action subsequentAction(BlockPos currentPosition) { List pos = positions(); - List moves = movements(); + List actions = actions(); for (int i = 0; i < pos.size(); i++) { if (currentPosition.equals(pos.get(i))) { - return moves.get(i); + return actions.get(i); } } throw new UnsupportedOperationException(currentPosition + " not in path"); diff --git a/src/main/java/baritone/bot/pathing/calc/Path.java b/src/main/java/baritone/bot/pathing/calc/Path.java index e945c5992..4bf9ac0e8 100644 --- a/src/main/java/baritone/bot/pathing/calc/Path.java +++ b/src/main/java/baritone/bot/pathing/calc/Path.java @@ -1,7 +1,7 @@ package baritone.bot.pathing.calc; +import baritone.bot.pathing.action.Action; import baritone.bot.pathing.goals.Goal; -import baritone.bot.pathing.movements.Movement; import net.minecraft.util.math.BlockPos; import java.util.ArrayList; @@ -23,34 +23,41 @@ class Path implements IPath { * path.get(path.size()-1) equals end */ public final ArrayList path; - final ArrayList movements; + final ArrayList actions; Path(PathNode start, PathNode end, Goal goal) { this.start = start.pos; this.end = end.pos; this.goal = goal; this.path = new ArrayList<>(); - this.movements = new ArrayList<>(); + this.actions = new ArrayList<>(); assemblePath(start, end); } private final void assemblePath(PathNode start, PathNode end) { PathNode current = end; LinkedList tempPath = new LinkedList<>();//repeatedly inserting to the beginning of an arraylist is O(n^2) - LinkedList tempMovements = new LinkedList<>();//instead, do it into a linked list, then convert at the end + LinkedList tempActions = new LinkedList<>();//instead, do it into a linked list, then convert at the end while (!current.equals(start)) { tempPath.addFirst(current.pos); - tempMovements.addFirst(current.previousMovement); + tempActions.addFirst(current.previousAction); current = current.previous; } tempPath.addFirst(start.pos); + //can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is + //inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able + //to performantly do that conversion since it knows the length. path.addAll(tempPath); - movements.addAll(tempMovements); + actions.addAll(tempActions); + } + + protected void sanityCheck() { + } @Override - public List movements() { - return movements; + public List actions() { + return actions; } @Override diff --git a/src/main/java/baritone/bot/pathing/calc/PathNode.java b/src/main/java/baritone/bot/pathing/calc/PathNode.java index 02bd5c04a..ed372e5d9 100644 --- a/src/main/java/baritone/bot/pathing/calc/PathNode.java +++ b/src/main/java/baritone/bot/pathing/calc/PathNode.java @@ -1,7 +1,7 @@ package baritone.bot.pathing.calc; +import baritone.bot.pathing.action.Action; import baritone.bot.pathing.goals.Goal; -import baritone.bot.pathing.movements.Movement; import net.minecraft.util.math.BlockPos; import java.util.Objects; @@ -19,7 +19,7 @@ class PathNode { // These three fields are mutable and are changed by PathFinder double cost; PathNode previous; - Movement previousMovement; + Action previousAction; /** * Is this a member of the open set in A*? (only used during pathfinding) @@ -36,7 +36,7 @@ class PathNode { this.cost = Short.MAX_VALUE; this.goal = goal; this.estimatedCostToGoal = goal.heuristic(pos); - this.previousMovement = null; + this.previousAction = null; this.isOpen = false; } @@ -48,7 +48,7 @@ class PathNode { 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); + hash = 3241543 * hash + Objects.hashCode(this.goal);//don't call goal.hashcode. this calls objects hashcode to verify that the actual goal objects are == identical, which is important for node caching return hash; } diff --git a/src/main/java/baritone/bot/pathing/movements/Movement.java b/src/main/java/baritone/bot/pathing/movements/Movement.java deleted file mode 100644 index ab85795fd..000000000 --- a/src/main/java/baritone/bot/pathing/movements/Movement.java +++ /dev/null @@ -1,35 +0,0 @@ -package baritone.bot.pathing.movements; - -import baritone.bot.pathing.action.Action; -import net.minecraft.util.math.BlockPos; - -import java.util.List; - -public abstract class Movement { - - /** - * Flat list of ordered actions - */ - protected List actions; - - /** - * Gets source block position for Movement. - * - * @return Movement's starting block position - */ - public abstract BlockPos getSrc(); - - /** - * Gets the block position the movement should finish at - * - * @return Movement's final block position - */ - public abstract BlockPos getDest(); - - /** - * Calculate the movement's cost - * - * @return Cost - */ - public abstract double calcCost(); -} diff --git a/src/main/java/baritone/bot/utils/BlockStateInterface.java b/src/main/java/baritone/bot/utils/BlockStateInterface.java new file mode 100644 index 000000000..2ff69c7bb --- /dev/null +++ b/src/main/java/baritone/bot/utils/BlockStateInterface.java @@ -0,0 +1,16 @@ +package baritone.bot.utils; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; + +public class BlockStateInterface { + public static IBlockState get(BlockPos pos) { // wrappers for future 1.13 compat + return Minecraft.getMinecraft().world.getBlockState(pos); + } + + public static Block getBlock(BlockPos pos) { + return get(pos).getBlock(); + } +} diff --git a/src/main/resources/baritone/pathfinding/actions/ActionDescendThree.java b/src/main/resources/baritone/pathfinding/actions/ActionDescendThree.java index 4464351e9..73033c8a8 100644 --- a/src/main/resources/baritone/pathfinding/actions/ActionDescendThree.java +++ b/src/main/resources/baritone/pathfinding/actions/ActionDescendThree.java @@ -6,7 +6,6 @@ import baritone.util.ToolSet; import net.minecraft.util.math.BlockPos; /** - * * @author leijurv */ public class ActionDescendThree extends ActionPlaceOrBreak {