tweaked physics and begun core pathfinder loop

This commit is contained in:
Leijurv
2021-08-20 16:27:36 -07:00
parent 5aa0dfc98c
commit 0b4e5f753a
3 changed files with 122 additions and 18 deletions

View File

@@ -50,6 +50,69 @@ public class GreedySolver {
while (!heap.isEmpty()) {
Node node = heap.removeLowest();
WorldState worldState = node.coalesceState(this);
long pos = node.pos();
BlockStateCachedData above = at((BetterBlockPos.toLong(0, 2, 0) + pos) & BetterBlockPos.POST_ADDITION_MASK, worldState);
BlockStateCachedData head = at(Face.UP.offset(pos), worldState);
if (Main.DEBUG && head.collidesWithPlayer) {
throw new IllegalStateException();
}
BlockStateCachedData feet = at(pos, worldState);
BlockStateCachedData underneath = at(Face.DOWN.offset(pos), worldState);
int blipsWithinBlock = PlayerPhysics.determinePlayerRealSupportLevel(underneath, feet);
if (blipsWithinBlock < 0) {
throw new IllegalStateException();
}
boolean stickingUpIntoThirdBlock = blipsWithinBlock > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE; // exactly equal means not sticking up, since overestimate means overestimate
int blips = node.y * Blip.PER_BLOCK + blipsWithinBlock;
mid:
for (Face travel : Face.HORIZONTALS) {
long newPos = travel.offset(pos);
BlockStateCachedData newAbove = at((BetterBlockPos.toLong(0, 2, 0) + newPos) & BetterBlockPos.POST_ADDITION_MASK, worldState);
BlockStateCachedData newHead = at(Face.UP.offset(newPos), worldState);
BlockStateCachedData newFeet = at(newPos, worldState);
BlockStateCachedData newUnderneath = at(Face.DOWN.offset(newPos), worldState);
switch (PlayerPhysics.playerTravelCollides(blipsWithinBlock, above, newAbove, newHead, newFeet, newUnderneath, underneath, feet)) {
case BLOCKED: {
// TODO ascend
continue;
}
case FALL: {
// this means that there is nothing preventing us from walking forward and falling
// iterate downwards to see what we would hit
for (int descent = 0; ; descent++) {
// NOTE: you cannot do (descent*Face.DOWN.offset)&BetterBlockPos.POST_ADDITION_MASK because Y is serialized into the center of the long. but I suppose you could do it with X. hm maybe Y should be moved to the most significant bits purely to allow this :^)
long support = (BetterBlockPos.toLong(0, -descent, 0) + newPos) & BetterBlockPos.POST_ADDITION_MASK;
BlockStateCachedData data = at(support, worldState);
BlockStateCachedData under = at(Face.DOWN.offset(support), worldState);
PlayerPhysics.VoxelResidency res = PlayerPhysics.canPlayerStand(under, data);
switch (res) {
case FLOATING:
continue; // as expected
case PREVENTED_BY_UNDERNEATH:
case PREVENTED_BY_WITHIN:
continue mid; // no safe landing
case IMPOSSIBLE_WITHOUT_SUFFOCATING:
throw new IllegalStateException();
case UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK:
case STANDARD_WITHIN_SUPPORT:
// found our landing spot
// TODO
}
}
// descent, with a possible fallthrough to VOXEL_LEVEL if it's just a troll
// no break, fallthrouh instead!
} // FALLTHROUGH!
case VOXEL_LEVEL: { // ^ POSSIBLE FALLTHROUGH ^
}
case VOXEL_UP: {
}
}
}
// consider actions:
// traverse

View File

@@ -58,10 +58,12 @@ public class PlaceOrderDependencyGraph {
public BlockStateCachedData data(long pos) {
int state = state(pos);
if (treatAsScaffolding(state)) {
BlockStateCachedData data = BlockStateCachedData.get(state);
if (treatAsScaffolding(data)) {
return BlockStateCachedData.SCAFFOLDING;
} else {
return data;
}
return BlockStateCachedData.get(state);
}
// example: dirt at 0,0,0 torch at 0,1,0. outgoingEdge(0,0,0,UP) returns true, incomingEdge(0,1,0,DOWN) returns true
@@ -88,7 +90,7 @@ public class PlaceOrderDependencyGraph {
}
public boolean airTreatedAsScaffolding(long pos) {
return treatAsScaffolding(state(pos));
return treatAsScaffolding(BlockStateCachedData.get(state(pos)));
}
private int state(long pos) {
@@ -103,7 +105,7 @@ public class PlaceOrderDependencyGraph {
return states.bounds;
}
private boolean treatAsScaffolding(int state) {
return BlockStateCachedData.get(state).isAir;
private boolean treatAsScaffolding(BlockStateCachedData state) {
return state.isAir;
}
}

View File

@@ -19,28 +19,67 @@ package baritone.builder;
public class PlayerPhysics {
public static int determinePlayerRealSupportLevel(BlockStateCachedData underneath, BlockStateCachedData within) {
switch (canPlayerStand(underneath, within)) {
case STANDARD_WITHIN_SUPPORT:
return within.collisionHeightBlips();
case UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK:
return underneath.collisionHeightBlips() - Blip.FULL_BLOCK;
default:
return -1;
}
}
/**
* the player Y is within within. i.e. the player Y is greater than or equal within and less than within+1
* <p>
* returns a negative value if impossible. returns a >=0 value if possible.
* underneath is the block underneath that, which we annoyingly also have to check due to fences and other blocks that are taller than a block
*/
public static int determinePlayerRealSupport(BlockStateCachedData underneath, BlockStateCachedData within) {
public static VoxelResidency canPlayerStand(BlockStateCachedData underneath, BlockStateCachedData within) {
if (within.collidesWithPlayer) {
if (underneath.collidesWithPlayer && underneath.collisionHeightBlips() - Blip.FULL_BLOCK > within.collisionHeightBlips()) { // > because imagine something like slab on top of fence, we can walk on the slab even though the fence is equivalent height
if (!underneath.fullyWalkableTop) {
return -1;
return VoxelResidency.PREVENTED_BY_UNDERNEATH;
}
return underneath.collisionHeightBlips() - Blip.FULL_BLOCK; // this could happen if "underneath" is a fence and "within" is a carpet
return VoxelResidency.UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK; // this could happen if "underneath" is a fence and "within" is a carpet
}
if (!within.fullyWalkableTop || within.collisionHeightBlips() >= Blip.FULL_BLOCK) {
return -1;
if (!within.fullyWalkableTop) {
return VoxelResidency.PREVENTED_BY_WITHIN;
}
return within.collisionHeightBlips();
if (within.collisionHeightBlips() >= Blip.FULL_BLOCK) {
return VoxelResidency.IMPOSSIBLE_WITHOUT_SUFFOCATING;
}
return VoxelResidency.STANDARD_WITHIN_SUPPORT;
} else {
if (!underneath.fullyWalkableTop || underneath.collisionHeightBlips() < Blip.FULL_BLOCK) { // short circuit only calls collisionHeightBlips when fullyWalkableTop is true, so this is safe
return -1;
if (!underneath.fullyWalkableTop) {
return VoxelResidency.PREVENTED_BY_UNDERNEATH;
}
return underneath.collisionHeightBlips() - Blip.FULL_BLOCK;
if (underneath.collisionHeightBlips() < Blip.FULL_BLOCK) { // short circuit only calls collisionHeightBlips when fullyWalkableTop is true, so this is safe
return VoxelResidency.FLOATING;
}
return VoxelResidency.UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK;
}
}
public enum VoxelResidency {
UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK, // i fucking hate notch for adding fences to the game. anyway this means that the height is underneath.collisionHeightBlips minus a full block.
STANDARD_WITHIN_SUPPORT, // :innocent: emoji, the height is simply the collisionHeightBlips of the within
IMPOSSIBLE_WITHOUT_SUFFOCATING, // aka: um we are literally underground
FLOATING, // aka: um we are literally floating in midair
PREVENTED_BY_UNDERNEATH, // fences :woozy_face:
PREVENTED_BY_WITHIN, // what are you even thinking?
}
public static boolean valid(VoxelResidency res) {
// FWIW this is equivalent to "return determinePlayerRealSupportLevel > 0"
switch (res) {
case UNDERNEATH_PROTRUDES_AT_OR_ABOVE_FULL_BLOCK:
case STANDARD_WITHIN_SUPPORT:
return true;
default:
return false;
}
}
@@ -66,7 +105,7 @@ public class PlayerPhysics {
if (Main.DEBUG && (feet < 0 || feet >= Blip.FULL_BLOCK)) {
throw new IllegalStateException();
}
if (Main.DEBUG && (feet != determinePlayerRealSupport(S, X))) {
if (Main.DEBUG && (feet != determinePlayerRealSupportLevel(S, X))) {
throw new IllegalStateException();
}
boolean alreadyWithinU = feet > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE; // > and not >= because the player height is a slight overestimate
@@ -78,7 +117,7 @@ public class PlayerPhysics {
}
int couldStepUpTo = feet + Blip.HALF_BLOCK;
// D cannot prevent us from doing anything because it cant be higher than 1.5. therefore, makes sense to check CB before DC.
int stepUp = determinePlayerRealSupport(C, B);
int stepUp = determinePlayerRealSupportLevel(C, B);
if (stepUp >= 0) {
// fundamentally a step upwards, from X to B instead of X to C
// too high?
@@ -97,7 +136,7 @@ public class PlayerPhysics {
if (B.collidesWithPlayer) { // we have ruled out stepping on top of B, so now if B is still colliding there is no way forward
return Collision.BLOCKED;
}
int stayLevel = determinePlayerRealSupport(D, C);
int stayLevel = determinePlayerRealSupportLevel(D, C);
if (stayLevel >= 0) {
// fundamentally staying within the same vertical voxel, X -> C
if (stayLevel > couldStepUpTo) {