misc tweaks, forgot to commit last week

This commit is contained in:
Leijurv
2021-05-24 12:52:34 -07:00
parent d501359857
commit a9b7b91a3c
4 changed files with 43 additions and 21 deletions

View File

@@ -34,11 +34,22 @@ public class Blip {
public static final int FULL_BLOCK = PER_BLOCK;
public static final double RATIO = 0.0625;
public static final int HALF_BLOCK = 8;
public static final int PLAYER_HEIGHT = 29;
public static final int PLAYER_HEIGHT_SLIGHT_UNDERESTIMATE = 28;
public static final int PLAYER_HEIGHT_SLIGHT_OVERESTIMATE = PLAYER_HEIGHT_SLIGHT_UNDERESTIMATE + 1;
public static final int TWO_BLOCKS = 2 * FULL_BLOCK;
public static final int FEET_TO_EYE_APPROX = (int) (IPlayerContext.eyeHeight(false) / RATIO);
public static double playerEyeFromFeetBlips(int feetBlips, boolean sneaking) {
return feetBlips * RATIO + IPlayerContext.eyeHeight(sneaking);
}
static {
double realPlayerHeight = 1.8;
if (PLAYER_HEIGHT_SLIGHT_OVERESTIMATE * RATIO <= realPlayerHeight || PLAYER_HEIGHT_SLIGHT_UNDERESTIMATE * RATIO >= realPlayerHeight) {
throw new IllegalStateException();
}
if (PER_BLOCK * RATIO != 1) {
throw new IllegalStateException();
}
}
}

View File

@@ -256,6 +256,9 @@ public class BlockStateCachedDataBuilder {
if (collisionHeightBlips != null && (collisionHeightBlips > Blip.FULL_BLOCK + Blip.HALF_BLOCK || collisionHeightBlips <= 0)) { // playerphysics assumes this is never true
throw new IllegalStateException();
}
if (collidesWithPlayer && collisionHeightBlips == null) {
throw new IllegalStateException();
}
if (fullyWalkableTop && !collidesWithPlayer) {
throw new IllegalStateException();
}

View File

@@ -134,6 +134,15 @@ public class BlockStatePlacementOption {
}
}
/**
* In EnumFacing.getDirectionFromEntityLiving, it checks if the player feet is within 2 blocks of the center of the block to be placed.
* Normally, this is a nonissue, but a problem arises because we are considering hypothetical placements where the player stands at the exact +0.5,+0.5 center of a block.
* In that case, it's possible for our hypothetical to have the player at precisely 2 blocks away, i.e. precisely on the edge of this condition being true or false.
* For that reason, we treat those exact cases as "ambiguous". So, if the distance is within this tolerance of 2 (so, 1.99 to 2.01), we treat it as a "could go either way",
* because when we really get there in-game, floating point inaccuracy could indeed actually make it go either way.
*/
private static final double ENTITY_FACING_TOLERANCE = 0.01;
private boolean directionOk(Vec3d eye, Vec3d hit) {
if (playerMustBeHorizontalFacing.isPresent()) {
return eye.flatDirectionTo(hit) == playerMustBeHorizontalFacing.get();
@@ -146,27 +155,25 @@ public class BlockStatePlacementOption {
// see EnumFacing.getDirectionFromEntityLiving
double dx = Math.abs(eye.x - 0.5);
double dz = Math.abs(eye.z - 0.5);
if (dx < 1.99 && dz < 1.99) {
// both within 2 = normal
if (eye.y < 0) {
if (dx < 2 - ENTITY_FACING_TOLERANCE && dz < 2 - ENTITY_FACING_TOLERANCE) { // < 1.99
if (eye.y < 0) { // eye below placement level = it will be facing down, so this is only okay if we wantthat
return entFace == Face.DOWN;
}
if (eye.y > 2) {
if (eye.y > 2) { // same for up, if y>2 then it will be facing up
return entFace == Face.UP;
}
} else if (!(dx > 2.01 || dz > 2.01)) {
// ambiguous case
// UP/DOWN are impossible (caught by flat check), and anything that could cause up/down instead of horizontal is also not allowed sadly
} else if (!(dx > 2 + ENTITY_FACING_TOLERANCE || dz > 2 + ENTITY_FACING_TOLERANCE)) { // > 2.01
// this is the ambiguous case, because we are neither unambiguously both-within-2 (previous case), nor unambiguously either-above-two (this elseif condition).
// UP/DOWN are impossible, but that's caught by flat check
if (eye.y < 0 || eye.y > 2) {
return false;
return false; // anything that could cause up/down instead of horizontal is also not allowed sadly
}
} // else either is above 2.01, putting us in simple horizontal mode, so fallthrough to flat condition is correct, yay
} // else we are in unambiguous either-above-two, putting us in simple horizontal mode, so fallthrough to flat condition is correct, yay
return eye.flatDirectionTo(hit) == entFace.opposite();
}
return true;
}
public static BlockStatePlacementOption get(Face against, Half half, Optional<Face> playerMustBeHorizontalFacing, Optional<Face> playerMustBeEntityFacing) {
BlockStatePlacementOption ret = PLACEMENT_OPTION_SINGLETON_CACHE[against.index][half.ordinal()][Face.OPTS.indexOf(playerMustBeHorizontalFacing)][Face.OPTS.indexOf(playerMustBeEntityFacing)];
if (ret == null) {

View File

@@ -21,6 +21,8 @@ public class PlayerPhysics {
/**
* 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.
*/
public static int determinePlayerRealSupport(BlockStateCachedData underneath, BlockStateCachedData within) {
if (within.collidesWithPlayer) {
@@ -52,7 +54,6 @@ public class PlayerPhysics {
* YB
* XC
* SD
*
*/
public static Collision playerTravelCollides(int feet,
BlockStateCachedData U,
@@ -68,7 +69,7 @@ public class PlayerPhysics {
if (Main.DEBUG && (feet != determinePlayerRealSupport(S, X))) {
throw new IllegalStateException();
}
boolean alreadyWithinU = feet > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT; // > and not >= because the player height is a slight overestimate
boolean alreadyWithinU = feet > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE; // > and not >= because the player height is a slight overestimate
if (Main.DEBUG && (alreadyWithinU && U.collidesWithPlayer)) {
throw new IllegalStateException();
}
@@ -92,27 +93,27 @@ public class PlayerPhysics {
}
return Collision.VOXEL_UP; // A is already checked, so that's it!
}
// betweenCandB is impossible. pessimistically, this means B is colliding. optimistically, this means B and C are air.
// stepUp is impossible. pessimistically, this means B is colliding. optimistically, this means B and C are air.
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);
if (stayLevel >= 0) {
// fundamentally staying within the same vertical voxel, X -> C
if (stayLevel > couldStepUpTo) {
return Collision.BLOCKED;
}
if (stayLevel > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT && !alreadyWithinU) { // step up, combined with our height, protrudes into U and A, AND we didn't already
if (stayLevel > Blip.TWO_BLOCKS - Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE && !alreadyWithinU) { // step up, combined with our height, protrudes into U and A, AND we didn't already
if (U.collidesWithPlayer) { // stayLevel could even be LESS than feet
return Collision.BLOCKED;
}
if (A.collidesWithPlayer) {
if (A.collidesWithPlayer) { // already checked (alreadyWithinU && A.collidesWithPlayer) earlier
return Collision.BLOCKED;
}
}
if (B.collidesWithPlayer) {
return Collision.BLOCKED; // obv, our head will go into B
}
return Collision.VOXEL_LEVEL;
}
if (B.collidesWithPlayer || C.collidesWithPlayer) {
if (C.collidesWithPlayer) {
return Collision.BLOCKED;
}
if (!D.collidesWithPlayer) {
@@ -132,7 +133,7 @@ public class PlayerPhysics {
}
static {
if (Blip.PLAYER_HEIGHT > Blip.TWO_BLOCKS || Blip.PLAYER_HEIGHT + Blip.HALF_BLOCK <= Blip.TWO_BLOCKS) {
if (Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE >= Blip.TWO_BLOCKS || Blip.PLAYER_HEIGHT_SLIGHT_OVERESTIMATE + Blip.HALF_BLOCK <= Blip.TWO_BLOCKS) {
throw new IllegalStateException("Assumptions made in playerTravelCollides");
}
}