add fullypassable to precomputeddata

This commit is contained in:
Leijurv 2023-01-15 00:56:30 -08:00
parent 6bbdba7a21
commit a3f70e7977
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
3 changed files with 78 additions and 38 deletions

View File

@ -37,7 +37,6 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import java.util.Optional;
@ -210,33 +209,10 @@ public interface MovementHelper extends ActionCosts, Helper {
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)
*
* @param context Calculation context to provide block state lookup
* @param x The block's x position
* @param y The block's y position
* @param z The block's z position
* @return Whether or not the block at the specified position
*/
static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
return fullyPassable(
context.bsi.access,
context.bsi.isPassableBlockPos.setPos(x, y, z),
context.bsi.get0(x, y, z)
);
}
static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) {
return fullyPassable(ctx.world(), pos, ctx.world().getBlockState(pos));
}
static boolean fullyPassable(IBlockAccess access, BlockPos pos, IBlockState state) {
static Ternary fullyPassableBlockState(IBlockState state) {
Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case
return true;
return YES;
}
// exceptions - blocks that are isPassable true, but we can't actually jump through
if (block == Blocks.FIRE
@ -252,10 +228,49 @@ public interface MovementHelper extends ActionCosts, Helper {
|| block instanceof BlockTrapDoor
|| block instanceof BlockEndPortal
|| block instanceof BlockSkull) {
return false;
return NO;
}
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
return block.isPassable(access, pos);
// at least in 1.12.2 vanilla, that is.....
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) {
// see PR #1087 for why
System.out.println("The block " + state.getBlock().getLocalizedName() + " requires a special case due to the exception " + exception.getMessage());
return MAYBE;
}
}
/**
* 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)
*/
static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
return fullyPassable(context, x, y, z, context.get(x, y, z));
}
static boolean fullyPassable(CalculationContext context, int x, int y, int z, IBlockState state) {
return context.precomputedData.fullyPassable(context.bsi, x, y, z, state);
}
static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) {
IBlockState state = ctx.world().getBlockState(pos);
Ternary fullyPassable = fullyPassableBlockState(state);
if (fullyPassable == YES) {
return true;
}
if (fullyPassable == NO) {
return false;
}
return fullyPassablePosition(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ(), state); // meh
}
static boolean fullyPassablePosition(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
return state.getBlock().isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z));
}
static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
@ -488,7 +503,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (context.assumeWalkOnWater) {
return false;
}
Block blockAbove = context.getBlock(x, y+1, z);
Block blockAbove = context.getBlock(x, y + 1, z);
if (blockAbove instanceof BlockLiquid) {
return false;
}

View File

@ -112,13 +112,13 @@ public class MovementParkour extends Movement {
maxJump = 3;
}
}
// check parkour jumps from smallest to largest for obstacles/walls and landing positions
int verifiedMaxJump = 1; // i - 1 (when i = 2)
for (int i = 2; i <= maxJump; i++) {
int destX = x + xDiff * i;
int destZ = z + zDiff * i;
// check head/feet
if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) {
break;
@ -126,10 +126,10 @@ public class MovementParkour extends Movement {
if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) {
break;
}
// 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 (!MovementHelper.fullyPassable(context, destX, y, destZ, destInto)) {
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;
@ -139,7 +139,7 @@ public class MovementParkour extends Movement {
}
break;
}
// 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
@ -156,14 +156,14 @@ public class MovementParkour extends Movement {
}
break;
}
if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) {
break;
}
verifiedMaxJump = i;
}
// parkour place starts here
if (!context.allowParkourPlace) {
return;

View File

@ -25,7 +25,7 @@ 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
public class PrecomputedData {
private final int[] data = new int[Block.BLOCK_STATE_IDS.size()];
@ -34,6 +34,8 @@ public class PrecomputedData { // TODO add isFullyPassable
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 static final int FULLY_PASSABLE_MASK = 1 << 5;
private static final int FULLY_PASSABLE_SPECIAL_MASK = 1 << 6;
private int fillData(int id, IBlockState state) {
int blockData = 0;
@ -54,6 +56,14 @@ public class PrecomputedData { // TODO add isFullyPassable
blockData |= CAN_WALK_THROUGH_SPECIAL_MASK;
}
Ternary fullyPassableState = MovementHelper.fullyPassableBlockState(state);
if (fullyPassableState == YES) {
blockData |= FULLY_PASSABLE_MASK;
}
if (fullyPassableState == MAYBE) {
blockData |= FULLY_PASSABLE_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?
@ -89,4 +99,19 @@ public class PrecomputedData { // TODO add isFullyPassable
return (blockData & CAN_WALK_THROUGH_MASK) != 0;
}
}
public boolean fullyPassable(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 & FULLY_PASSABLE_SPECIAL_MASK) != 0) {
return MovementHelper.fullyPassablePosition(bsi, x, y, z, state);
} else {
return (blockData & FULLY_PASSABLE_MASK) != 0;
}
}
}