commit
2533cbc2c1
@ -9,6 +9,7 @@
|
|||||||
- **Slabs and stairs**
|
- **Slabs and stairs**
|
||||||
- **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore).
|
- **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore).
|
||||||
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
|
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
|
||||||
|
- **Parkour** Sprint jumping over 1, 2, or 3 block gaps
|
||||||
|
|
||||||
# Pathing method
|
# Pathing method
|
||||||
Baritone uses a modified version of A*.
|
Baritone uses a modified version of A*.
|
||||||
@ -42,7 +43,7 @@ Things it doesn't have yet
|
|||||||
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.
|
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.
|
||||||
|
|
||||||
Things it may not ever have, from most likely to least likely =(
|
Things it may not ever have, from most likely to least likely =(
|
||||||
- Boats
|
|
||||||
- Pigs
|
- Pigs
|
||||||
|
- Boats
|
||||||
- Horses (2x3 path instead of 1x2)
|
- Horses (2x3 path instead of 1x2)
|
||||||
- Elytra
|
- Elytra
|
||||||
|
@ -83,6 +83,13 @@ public class Settings {
|
|||||||
*/
|
*/
|
||||||
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You know what it is
|
||||||
|
* <p>
|
||||||
|
* But it's very unreliable and falls off when cornering like all the time so.
|
||||||
|
*/
|
||||||
|
public Setting<Boolean> allowParkour = new Setting<>(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
|
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
|
||||||
*/
|
*/
|
||||||
|
@ -233,7 +233,11 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
|||||||
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST),
|
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST),
|
||||||
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST),
|
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST),
|
||||||
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST),
|
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST),
|
||||||
new MovementPillar(pos, new BetterBlockPos(x, y + 1, z))
|
new MovementPillar(pos, new BetterBlockPos(x, y + 1, z)),
|
||||||
|
MovementParkour.calculate(pos, EnumFacing.NORTH),
|
||||||
|
MovementParkour.calculate(pos, EnumFacing.SOUTH),
|
||||||
|
MovementParkour.calculate(pos, EnumFacing.EAST),
|
||||||
|
MovementParkour.calculate(pos, EnumFacing.WEST),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ public abstract class Movement implements Helper, MovementHelper {
|
|||||||
return getCost(null);
|
return getCost(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void override(double cost) {
|
||||||
|
this.cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
public double calculateCostWithoutCaching() {
|
public double calculateCostWithoutCaching() {
|
||||||
return calculateCost(new CalculationContext());
|
return calculateCost(new CalculationContext());
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,9 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||||||
|
|
||||||
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
|
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
|
||||||
Block block = state.getBlock();
|
Block block = state.getBlock();
|
||||||
|
if (block == Blocks.AIR) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (block instanceof BlockFire || block instanceof BlockTripWire || block instanceof BlockWeb || block instanceof BlockEndPortal) {
|
if (block instanceof BlockFire || block instanceof BlockTripWire || block instanceof BlockWeb || block instanceof BlockEndPortal) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -103,6 +106,38 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||||||
return block.isPassable(mc.world, pos);
|
return block.isPassable(mc.world, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
|
||||||
|
* not including water, and not including ladders or vines or cobwebs (they slow us down)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static boolean fullyPassable(BlockPos pos) {
|
||||||
|
return fullyPassable(pos, BlockStateInterface.get(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean fullyPassable(BlockPos pos, IBlockState state) {
|
||||||
|
Block block = state.getBlock();
|
||||||
|
if (block == Blocks.AIR) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// exceptions - blocks that are isPassasble true, but we can't actually jump through
|
||||||
|
if (block == Blocks.FIRE
|
||||||
|
|| block == Blocks.TRIPWIRE
|
||||||
|
|| block == Blocks.WEB
|
||||||
|
|| block == Blocks.VINE
|
||||||
|
|| block == Blocks.LADDER
|
||||||
|
|| block instanceof BlockDoor
|
||||||
|
|| block instanceof BlockFenceGate
|
||||||
|
|| block instanceof BlockSnow
|
||||||
|
|| block instanceof BlockLiquid
|
||||||
|
|| block instanceof BlockTrapDoor
|
||||||
|
|| block instanceof BlockEndPortal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return block.isPassable(mc.world, pos);
|
||||||
|
}
|
||||||
|
|
||||||
static boolean isReplacable(BlockPos pos, IBlockState state) {
|
static boolean isReplacable(BlockPos pos, IBlockState state) {
|
||||||
// for MovementTraverse and MovementAscend
|
// for MovementTraverse and MovementAscend
|
||||||
// block double plant defaults to true when the block doesn't match, so don't need to check that case
|
// block double plant defaults to true when the block doesn't match, so don't need to check that case
|
||||||
|
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Baritone.
|
||||||
|
*
|
||||||
|
* Baritone is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Baritone is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package baritone.pathing.movement.movements;
|
||||||
|
|
||||||
|
import baritone.Baritone;
|
||||||
|
import baritone.pathing.movement.CalculationContext;
|
||||||
|
import baritone.pathing.movement.Movement;
|
||||||
|
import baritone.pathing.movement.MovementHelper;
|
||||||
|
import baritone.pathing.movement.MovementState;
|
||||||
|
import baritone.utils.BlockStateInterface;
|
||||||
|
import baritone.utils.InputOverrideHandler;
|
||||||
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.util.EnumFacing;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
public class MovementParkour extends Movement {
|
||||||
|
|
||||||
|
final EnumFacing direction;
|
||||||
|
final int dist;
|
||||||
|
|
||||||
|
private MovementParkour(BlockPos src, int dist, EnumFacing dir) {
|
||||||
|
super(src, src.offset(dir, dist), new BlockPos[]{});
|
||||||
|
this.direction = dir;
|
||||||
|
this.dist = dist;
|
||||||
|
super.override(costFromJumpDistance(dist));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovementParkour calculate(BlockPos src, EnumFacing dir) {
|
||||||
|
if (!Baritone.settings().allowParkour.get()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
IBlockState standingOn = BlockStateInterface.get(src.down());
|
||||||
|
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlockPos adjBlock = src.down().offset(dir);
|
||||||
|
IBlockState adj = BlockStateInterface.get(adjBlock);
|
||||||
|
if (MovementHelper.avoidWalkingInto(adj.getBlock())) { // magma sucks
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (MovementHelper.canWalkOn(adjBlock, adj)) { // don't parkour if we could just traverse (for now)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MovementHelper.fullyPassable(src.offset(dir))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!MovementHelper.fullyPassable(src.up().offset(dir))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (int i = 2; i <= 4; i++) {
|
||||||
|
BlockPos dest = src.offset(dir, i);
|
||||||
|
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
|
||||||
|
for (int y = 0; y < 4; y++) {
|
||||||
|
if (!MovementHelper.fullyPassable(dest.up(y))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MovementHelper.canWalkOn(dest.down())) {
|
||||||
|
return new MovementParkour(src, i, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double costFromJumpDistance(int dist) {
|
||||||
|
switch (dist) {
|
||||||
|
case 2:
|
||||||
|
return WALK_ONE_BLOCK_COST * 2; // IDK LOL
|
||||||
|
case 3:
|
||||||
|
return WALK_ONE_BLOCK_COST * 3;
|
||||||
|
case 4:
|
||||||
|
return SPRINT_ONE_BLOCK_COST * 4;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("LOL");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double calculateCost(CalculationContext context) {
|
||||||
|
if (!MovementHelper.canWalkOn(dest.down())) {
|
||||||
|
return COST_INF;
|
||||||
|
}
|
||||||
|
if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(src.down().offset(direction)).getBlock())) {
|
||||||
|
return COST_INF;
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
BlockPos d = src.offset(direction, i);
|
||||||
|
for (int y = 0; y < 4; y++) {
|
||||||
|
if (!MovementHelper.fullyPassable(d.up(y))) {
|
||||||
|
return COST_INF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d.equals(dest)) {
|
||||||
|
return costFromJumpDistance(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("invalid jump distance?");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MovementState updateState(MovementState state) {
|
||||||
|
super.updateState(state);
|
||||||
|
switch (state.getStatus()) {
|
||||||
|
case WAITING:
|
||||||
|
state.setStatus(MovementState.MovementStatus.RUNNING);
|
||||||
|
case RUNNING:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
if (dist >= 4) {
|
||||||
|
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||||
|
}
|
||||||
|
MovementHelper.moveTowards(state, dest);
|
||||||
|
if (playerFeet().equals(dest)) {
|
||||||
|
if (player().posY - playerFeet().getY() < 0.01) {
|
||||||
|
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||||
|
}
|
||||||
|
} else if (!playerFeet().equals(src)) {
|
||||||
|
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
|
||||||
|
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||||
|
} else {
|
||||||
|
state.setInput(InputOverrideHandler.Input.SPRINT, false);
|
||||||
|
if (playerFeet().equals(src.offset(direction, -1))) {
|
||||||
|
MovementHelper.moveTowards(state, src);
|
||||||
|
} else {
|
||||||
|
MovementHelper.moveTowards(state, src.offset(direction, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
@ -119,4 +119,10 @@ public final class BetterBlockPos extends BlockPos {
|
|||||||
Vec3i vec = dir.getDirectionVec();
|
Vec3i vec = dir.getDirectionVec();
|
||||||
return new BetterBlockPos(x + vec.getX(), y + vec.getY(), z + vec.getZ());
|
return new BetterBlockPos(x + vec.getX(), y + vec.getY(), z + vec.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos offset(EnumFacing dir, int dist) {
|
||||||
|
Vec3i vec = dir.getDirectionVec();
|
||||||
|
return new BetterBlockPos(x + vec.getX() * dist, y + vec.getY() * dist, z + vec.getZ() * dist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user