Merge pull request #3479 from scorbett123/caching_performance_upgrade
Caching performance upgrade
This commit is contained in:
commit
1697293f12
@ -34,8 +34,8 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Baritone's settings. Settings apply to all Baritone instances.
|
||||
|
@ -176,7 +176,7 @@ public class SettingsUtil {
|
||||
/**
|
||||
* This should always be the same as whether the setting can be parsed from or serialized to a string
|
||||
*
|
||||
* @param the setting
|
||||
* @param setting The Setting
|
||||
* @return true if the setting can not be set or read by the user
|
||||
*/
|
||||
public static boolean javaOnlySetting(Settings.Setting setting) {
|
||||
|
@ -99,6 +99,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
baritone.getPathingControlManager().cancelEverything();
|
||||
return;
|
||||
}
|
||||
|
||||
expectedSegmentStart = pathStart();
|
||||
baritone.getPathingControlManager().preTick();
|
||||
tickPath();
|
||||
|
@ -147,7 +147,8 @@ public class SetCommand extends Command {
|
||||
throw new CommandInvalidTypeException(args.consumed(), "a toggleable setting", "some other setting");
|
||||
}
|
||||
//noinspection unchecked
|
||||
((Settings.Setting<Boolean>) setting).value ^= true;
|
||||
Settings.Setting<Boolean> asBoolSetting = (Settings.Setting<Boolean>) setting;
|
||||
asBoolSetting.value ^= true;
|
||||
logDirect(String.format(
|
||||
"Toggled setting %s to %s",
|
||||
setting.getName(),
|
||||
|
@ -21,6 +21,7 @@ import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.pathing.precompute.PrecomputedData;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.ToolSet;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
@ -76,11 +77,14 @@ public class CalculationContext {
|
||||
public final double walkOnWaterOnePenalty;
|
||||
public final BetterWorldBorder worldBorder;
|
||||
|
||||
public final PrecomputedData precomputedData;
|
||||
|
||||
public CalculationContext(IBaritone baritone) {
|
||||
this(baritone, false);
|
||||
}
|
||||
|
||||
public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) {
|
||||
this.precomputedData = new PrecomputedData();
|
||||
this.safeForThreadedUse = forUseOnAnotherThread;
|
||||
this.baritone = baritone;
|
||||
EntityPlayerSP player = baritone.getPlayerContext().player();
|
||||
|
@ -25,6 +25,7 @@ import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.pathing.precompute.Ternary;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.block.*;
|
||||
@ -40,6 +41,7 @@ import net.minecraft.world.IBlockAccess;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP;
|
||||
import static baritone.pathing.precompute.Ternary.*;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
@ -88,29 +90,81 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z, IBlockState state) {
|
||||
return context.precomputedData.canWalkThrough(context.bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z) {
|
||||
return context.precomputedData.canWalkThrough(context.bsi, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) { // early return for most common case
|
||||
Ternary canWalkThrough = canWalkThroughBlockState(state);
|
||||
if (canWalkThrough == YES) {
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) {
|
||||
if (canWalkThrough == NO) {
|
||||
return false;
|
||||
}
|
||||
return canWalkThroughPosition(bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static Ternary canWalkThroughBlockState(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) {
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor || block == Blocks.END_ROD) {
|
||||
return NO;
|
||||
}
|
||||
if (Baritone.settings().blocksToAvoid.value.contains(block)) {
|
||||
return false;
|
||||
return NO;
|
||||
}
|
||||
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
|
||||
// Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume
|
||||
// that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't
|
||||
// be opened by just interacting.
|
||||
return block != Blocks.IRON_DOOR;
|
||||
// TODO this assumes that all doors in all mods are openable
|
||||
if (block == Blocks.IRON_DOOR) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.CARPET) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (block instanceof BlockSnow) {
|
||||
// snow layers cached as the top layer of a packed chunk have no metadata, we can't make a decision based on their depth here
|
||||
// it would otherwise make long distance pathing through snowy biomes impossible
|
||||
return MAYBE;
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
if (state.getValue(BlockLiquid.LEVEL) != 0) {
|
||||
return NO;
|
||||
} else {
|
||||
return MAYBE;
|
||||
}
|
||||
}
|
||||
if (block instanceof BlockCauldron) {
|
||||
return NO;
|
||||
}
|
||||
try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information
|
||||
if (block.isPassable(null, null)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} catch (Throwable exception) {
|
||||
System.out.println("The block " + state.getBlock().getLocalizedName() + " requires a special case due to the exception " + exception.getMessage());
|
||||
return MAYBE;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean canWalkThroughPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block == Blocks.CARPET) {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
|
||||
if (block instanceof BlockSnow) {
|
||||
// we've already checked doors and fence gates
|
||||
// so the only remaining dynamic isPassables are snow and trapdoor
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (!bsi.worldContainsLoadedChunk(x, z)) {
|
||||
@ -124,25 +178,27 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// ok, it's low enough we could walk through it, but is it supported?
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
if (isFlowing(x, y, z, state, bsi)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
|
||||
if (block instanceof BlockLiquid) {
|
||||
if (isFlowing(x, y, z, state, bsi)) {
|
||||
return false;
|
||||
}
|
||||
// Everything after this point has to be a special case as it relies on the water not being flowing, which means a special case is needed.
|
||||
if (Baritone.settings().assumeWalkOnWater.value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IBlockState up = bsi.get0(x, y + 1, z);
|
||||
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
return false;
|
||||
}
|
||||
return block == Blocks.WATER || block == Blocks.FLOWING_WATER;
|
||||
}
|
||||
if (block instanceof BlockCauldron) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
@ -284,6 +340,8 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* Can I walk on this block without anything weird happening like me falling
|
||||
* through? Includes water because we know that we automatically jump on
|
||||
* water
|
||||
* <p>
|
||||
* If changing something in this function remember to also change it in precomputed data
|
||||
*
|
||||
* @param bsi Block state provider
|
||||
* @param x The block's x position
|
||||
@ -293,32 +351,67 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return Whether or not the specified block can be walked on
|
||||
*/
|
||||
static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR || block == Blocks.MAGMA) {
|
||||
// early return for most common case (air)
|
||||
// plus magma, which is a normal cube but it hurts you
|
||||
Ternary canWalkOn = canWalkOnBlockState(state);
|
||||
if (canWalkOn == YES) {
|
||||
return true;
|
||||
}
|
||||
if (canWalkOn == NO) {
|
||||
return false;
|
||||
}
|
||||
if (state.isBlockNormalCube()) {
|
||||
return true;
|
||||
return canWalkOnPosition(bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static Ternary canWalkOnBlockState(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (state.isBlockNormalCube() && block != Blocks.MAGMA) {
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) {
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) {
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
|
||||
return YES;
|
||||
}
|
||||
if (block instanceof BlockStairs) {
|
||||
return YES;
|
||||
}
|
||||
if (isWater(block)) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (MovementHelper.isLava(block) && Baritone.settings().assumeWalkOnLava.value) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.value) {
|
||||
if (((BlockSlab) block).isDouble()) {
|
||||
return YES;
|
||||
}
|
||||
if (state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
static boolean canWalkOnPosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (isWater(block)) {
|
||||
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think it's a decrease in readability
|
||||
Block up = bsi.get0(x, y + 1, z).getBlock();
|
||||
if (up == Blocks.WATERLILY || up == Blocks.CARPET) {
|
||||
return true;
|
||||
}
|
||||
if (isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) {
|
||||
if (MovementHelper.isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return isWater(up) && !Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
@ -326,22 +419,20 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
if (Baritone.settings().assumeWalkOnLava.value && isLava(block) && !isFlowing(x, y, z, state, bsi)) {
|
||||
|
||||
if (MovementHelper.isLava(block) && !MovementHelper.isFlowing(x, y, z, state, bsi) && Baritone.settings().assumeWalkOnLava.value) { // if we get here it means that assumeWalkOnLava must be true, so put it last
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
|
||||
return true;
|
||||
|
||||
return false; // If we don't recognise it then we want to just return false to be safe.
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.value) {
|
||||
if (((BlockSlab) block).isDouble()) {
|
||||
return true;
|
||||
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z, IBlockState state) {
|
||||
return context.precomputedData.canWalkOn(context.bsi, x, y, z, state);
|
||||
}
|
||||
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return block instanceof BlockStairs;
|
||||
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z) {
|
||||
return canWalkOn(context, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos, IBlockState state) {
|
||||
@ -388,7 +479,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(context.bsi, x, y, z, state)) {
|
||||
if (!canWalkThrough(context, x, y, z, state)) {
|
||||
if (block instanceof BlockLiquid) {
|
||||
return COST_INF;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public class MovementAscend extends Movement {
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
IBlockState toPlace = context.get(destX, y, destZ);
|
||||
double additionalPlacementCost = 0;
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y, destZ, toPlace)) {
|
||||
additionalPlacementCost = context.costOfPlacingAt(destX, y, destZ, toPlace);
|
||||
if (additionalPlacementCost >= COST_INF) {
|
||||
return COST_INF;
|
||||
@ -94,7 +94,7 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
}
|
||||
IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway
|
||||
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
|
||||
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
|
@ -101,7 +101,7 @@ public class MovementDescend extends Movement {
|
||||
//C, D, etc determine the length of the fall
|
||||
|
||||
IBlockState below = context.get(destX, y - 2, destZ);
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ, below)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y - 2, destZ, below)) {
|
||||
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
|
||||
return;
|
||||
}
|
||||
@ -130,7 +130,7 @@ public class MovementDescend extends Movement {
|
||||
// and potentially replace the water we're going to fall into
|
||||
return false;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y - 2, destZ, below)) {
|
||||
return false;
|
||||
}
|
||||
double costSoFar = 0;
|
||||
@ -146,7 +146,7 @@ public class MovementDescend extends Movement {
|
||||
int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY
|
||||
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar;
|
||||
if (MovementHelper.isWater(ontoBlock.getBlock())) {
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) {
|
||||
return false;
|
||||
}
|
||||
if (context.assumeWalkOnWater) {
|
||||
@ -155,7 +155,7 @@ public class MovementDescend extends Movement {
|
||||
if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) {
|
||||
return false; // TODO flowing check required here?
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, newY - 1, destZ)) {
|
||||
// we could punch right through the water into something else
|
||||
return false;
|
||||
}
|
||||
@ -174,10 +174,10 @@ public class MovementDescend extends Movement {
|
||||
effectiveStartHeight = newY;
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) {
|
||||
return false;
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(ontoBlock)) {
|
||||
|
@ -60,7 +60,7 @@ public class MovementDiagonal extends Movement {
|
||||
@Override
|
||||
protected boolean safeToCancel(MovementState state) {
|
||||
//too simple. backfill does not work after cornering with this
|
||||
//return MovementHelper.canWalkOn(ctx, ctx.playerFeet().down());
|
||||
//return context.precomputedData.canWalkOn(ctx, ctx.playerFeet().down());
|
||||
EntityPlayerSP player = ctx.player();
|
||||
double offset = 0.25;
|
||||
double x = player.posX;
|
||||
@ -110,24 +110,24 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y + 1, destZ)) {
|
||||
return;
|
||||
}
|
||||
IBlockState destInto = context.get(destX, y, destZ);
|
||||
boolean ascend = false;
|
||||
IBlockState destWalkOn;
|
||||
boolean descend = false;
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y, destZ, destInto)) {
|
||||
ascend = true;
|
||||
if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context.bsi, x, y + 2, z) || !MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 2, destZ)) {
|
||||
if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context, x, y + 2, z) || !MovementHelper.canWalkOn(context, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context, destX, y + 2, destZ)) {
|
||||
return;
|
||||
}
|
||||
destWalkOn = destInto;
|
||||
} else {
|
||||
destWalkOn = context.get(destX, y - 1, destZ);
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y - 1, destZ, destWalkOn)) {
|
||||
descend = true;
|
||||
if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) {
|
||||
if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context, destX, y - 1, destZ, destWalkOn)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -169,17 +169,17 @@ public class MovementDiagonal extends Movement {
|
||||
IBlockState pb0 = context.get(x, y, destZ);
|
||||
IBlockState pb2 = context.get(destX, y, z);
|
||||
if (ascend) {
|
||||
boolean ATop = MovementHelper.canWalkThrough(context.bsi, x, y + 2, destZ);
|
||||
boolean AMid = MovementHelper.canWalkThrough(context.bsi, x, y + 1, destZ);
|
||||
boolean ALow = MovementHelper.canWalkThrough(context.bsi, x, y, destZ, pb0);
|
||||
boolean BTop = MovementHelper.canWalkThrough(context.bsi, destX, y + 2, z);
|
||||
boolean BMid = MovementHelper.canWalkThrough(context.bsi, destX, y + 1, z);
|
||||
boolean BLow = MovementHelper.canWalkThrough(context.bsi, destX, y, z, pb2);
|
||||
boolean ATop = MovementHelper.canWalkThrough(context, x, y + 2, destZ);
|
||||
boolean AMid = MovementHelper.canWalkThrough(context, x, y + 1, destZ);
|
||||
boolean ALow = MovementHelper.canWalkThrough(context, x, y, destZ, pb0);
|
||||
boolean BTop = MovementHelper.canWalkThrough(context, destX, y + 2, z);
|
||||
boolean BMid = MovementHelper.canWalkThrough(context, destX, y + 1, z);
|
||||
boolean BLow = MovementHelper.canWalkThrough(context, destX, y, z, pb2);
|
||||
if ((!(ATop && AMid && ALow) && !(BTop && BMid && BLow)) // no option
|
||||
|| MovementHelper.avoidWalkingInto(pb0.getBlock()) // bad
|
||||
|| MovementHelper.avoidWalkingInto(pb2.getBlock()) // bad
|
||||
|| (ATop && AMid && MovementHelper.canWalkOn(context.bsi, x, y, destZ, pb0)) // we could just ascend
|
||||
|| (BTop && BMid && MovementHelper.canWalkOn(context.bsi, destX, y, z, pb2)) // we could just ascend
|
||||
|| (ATop && AMid && MovementHelper.canWalkOn(context, x, y, destZ, pb0)) // we could just ascend
|
||||
|| (BTop && BMid && MovementHelper.canWalkOn(context, destX, y, z, pb2)) // we could just ascend
|
||||
|| (!ATop && AMid && ALow) // head bonk A
|
||||
|| (!BTop && BMid && BLow)) { // head bonk B
|
||||
return;
|
||||
|
@ -59,7 +59,7 @@ public class MovementDownward extends Movement {
|
||||
if (!context.allowDownward) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) {
|
||||
if (!MovementHelper.canWalkOn(context, x, y - 2, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState down = context.get(x, y - 1, z);
|
||||
|
@ -74,7 +74,7 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff);
|
||||
if (MovementHelper.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
// second most common case -- we could just traverse not parkour
|
||||
return;
|
||||
}
|
||||
@ -122,7 +122,7 @@ public class MovementParkour extends Movement {
|
||||
// check for ascend landing position
|
||||
IBlockState destInto = context.bsi.get0(destX, y, destZ);
|
||||
if (!MovementHelper.fullyPassable(context.bsi.access, context.bsi.isPassableBlockPos.setPos(destX, y, destZ), destInto)) {
|
||||
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
|
||||
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y + 1;
|
||||
res.z = destZ;
|
||||
@ -135,7 +135,7 @@ public class MovementParkour extends Movement {
|
||||
// check for flat landing position
|
||||
IBlockState landingOn = context.bsi.get0(destX, y - 1, destZ);
|
||||
// farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha
|
||||
if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) {
|
||||
if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn)) {
|
||||
if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
|
@ -120,7 +120,7 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
}
|
||||
// this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era.
|
||||
//if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
|
||||
//if (!MovementHelper.canWalkOn(context, chkPos, check) || MovementHelper.canWalkThrough(context, chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
|
||||
// TODO why does canWalkThrough mean this action is COST_INF?
|
||||
// BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava
|
||||
// but I don't understand why canWalkThrough makes it impossible
|
||||
|
@ -72,7 +72,7 @@ public class MovementTraverse extends Movement {
|
||||
IBlockState pb1 = context.get(destX, y, destZ);
|
||||
IBlockState destOn = context.get(destX, y - 1, destZ);
|
||||
Block srcDown = context.getBlock(x, y - 1, z);
|
||||
if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
if (MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
boolean water = false;
|
||||
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
|
||||
|
@ -350,7 +350,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
|
||||
|
||||
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
|
||||
if (!new CalculationContext(behavior.baritone).canSprint) {
|
||||
if (!new CalculationContext(behavior.baritone, false).canSprint) {
|
||||
return false;
|
||||
}
|
||||
IMovement current = path.movements().get(pathPosition);
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.precompute;
|
||||
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import static baritone.pathing.precompute.Ternary.MAYBE;
|
||||
import static baritone.pathing.precompute.Ternary.YES;
|
||||
|
||||
public class PrecomputedData { // TODO add isFullyPassable
|
||||
|
||||
private final int[] data = new int[Block.BLOCK_STATE_IDS.size()];
|
||||
|
||||
private static final int COMPLETED_MASK = 1 << 0;
|
||||
private static final int CAN_WALK_ON_MASK = 1 << 1;
|
||||
private static final int CAN_WALK_ON_SPECIAL_MASK = 1 << 2;
|
||||
private static final int CAN_WALK_THROUGH_MASK = 1 << 3;
|
||||
private static final int CAN_WALK_THROUGH_SPECIAL_MASK = 1 << 4;
|
||||
|
||||
private int fillData(int id, IBlockState state) {
|
||||
int blockData = 0;
|
||||
|
||||
Ternary canWalkOnState = MovementHelper.canWalkOnBlockState(state);
|
||||
if (canWalkOnState == YES) {
|
||||
blockData |= CAN_WALK_ON_MASK;
|
||||
}
|
||||
if (canWalkOnState == MAYBE) {
|
||||
blockData |= CAN_WALK_ON_SPECIAL_MASK;
|
||||
}
|
||||
|
||||
Ternary canWalkThroughState = MovementHelper.canWalkThroughBlockState(state);
|
||||
if (canWalkThroughState == YES) {
|
||||
blockData |= CAN_WALK_THROUGH_MASK;
|
||||
}
|
||||
if (canWalkOnState == MAYBE) {
|
||||
blockData |= CAN_WALK_THROUGH_SPECIAL_MASK;
|
||||
}
|
||||
|
||||
blockData |= COMPLETED_MASK;
|
||||
|
||||
data[id] = blockData; // in theory, this is thread "safe" because every thread should compute the exact same int to write?
|
||||
return blockData;
|
||||
}
|
||||
|
||||
public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
int id = Block.BLOCK_STATE_IDS.get(state);
|
||||
int blockData = data[id];
|
||||
|
||||
if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data
|
||||
blockData = fillData(id, state);
|
||||
}
|
||||
|
||||
if ((blockData & CAN_WALK_ON_SPECIAL_MASK) != 0) {
|
||||
return MovementHelper.canWalkOnPosition(bsi, x, y, z, state);
|
||||
} else {
|
||||
return (blockData & CAN_WALK_ON_MASK) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
int id = Block.BLOCK_STATE_IDS.get(state);
|
||||
int blockData = data[id];
|
||||
|
||||
if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data
|
||||
blockData = fillData(id, state);
|
||||
}
|
||||
|
||||
if ((blockData & CAN_WALK_THROUGH_SPECIAL_MASK) != 0) {
|
||||
return MovementHelper.canWalkThroughPosition(bsi, x, y, z, state);
|
||||
} else {
|
||||
return (blockData & CAN_WALK_THROUGH_MASK) != 0;
|
||||
}
|
||||
}
|
||||
}
|
22
src/main/java/baritone/pathing/precompute/Ternary.java
Normal file
22
src/main/java/baritone/pathing/precompute/Ternary.java
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.precompute;
|
||||
|
||||
public enum Ternary {
|
||||
YES, MAYBE, NO
|
||||
}
|
@ -28,6 +28,7 @@ import baritone.cache.CachedChunk;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.precompute.PrecomputedData;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
|
Loading…
Reference in New Issue
Block a user