Better world border collision check + WorldBorder#getCollisionAxis

This commit is contained in:
Felix Cravic 2020-05-27 01:15:21 +02:00
parent ef261c1792
commit f5f5a6bb4e
2 changed files with 50 additions and 15 deletions

View File

@ -312,13 +312,28 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
);
onGround = CollisionUtils.handlePhysics(this, deltaPos, newPosition, newVelocityOut);
WorldBorder worldBorder = instance.getWorldBorder();
if (worldBorder.isInside(newPosition)) {
// Apply velocity + gravity
refreshPosition(newPosition);
} else {
// Only apply Y velocity/gravity
refreshPosition(position.getX(), newPosition.getY(), position.getZ());
// World border collision
{
WorldBorder worldBorder = instance.getWorldBorder();
WorldBorder.CollisionAxis collisionAxis = worldBorder.getCollisionAxis(newPosition);
switch (collisionAxis) {
case NONE:
// Apply velocity + gravity
refreshPosition(newPosition);
break;
case BOTH:
// Apply Y velocity/gravity
refreshPosition(position.getX(), newPosition.getY(), position.getZ());
break;
case X:
// Apply Y/Z velocity/gravity
refreshPosition(position.getX(), newPosition.getY(), newPosition.getZ());
break;
case Z:
// Apply X/Y velocity/gravity
refreshPosition(newPosition.getX(), newPosition.getY(), position.getZ());
break;
}
}
velocity.copy(newVelocityOut);

View File

@ -41,7 +41,7 @@ public class WorldBorder {
refreshCenter();
}
public double getCenterX() {
public float getCenterX() {
return centerX;
}
@ -50,7 +50,7 @@ public class WorldBorder {
refreshCenter();
}
public double getCenterZ() {
public float getCenterZ() {
return centerZ;
}
@ -136,6 +136,26 @@ public class WorldBorder {
sendPacket(worldBorderPacket);
}
/**
* Used to check at which axis does the position collides with the world border
*
* @param position the position to check
* @return the axis where the position collides with the world border
*/
public CollisionAxis getCollisionAxis(Position position) {
final double radius = getDiameter() / 2d;
final boolean checkX = position.getX() <= getCenterX() + radius && position.getX() >= getCenterX() - radius;
final boolean checkZ = position.getZ() <= getCenterZ() + radius && position.getZ() >= getCenterZ() - radius;
if (!checkX && !checkZ) {
return CollisionAxis.BOTH;
} else if (!checkX) {
return CollisionAxis.X;
} else if (!checkZ) {
return CollisionAxis.Z;
}
return CollisionAxis.NONE;
}
/**
* Used to know if a position is located inside the world border or not
*
@ -143,12 +163,7 @@ public class WorldBorder {
* @return true if {@code position} is inside the world border, false otherwise
*/
public boolean isInside(Position position) {
final double radius = getDiameter() / 2d;
final boolean checkX = position.getX() < getCenterX() + radius && position.getX() > getCenterX() - radius;
if (!checkX)
return false;
final boolean checkZ = position.getZ() < getCenterZ() + radius && position.getZ() > getCenterZ() - radius;
return checkZ;
return getCollisionAxis(position) == CollisionAxis.NONE;
}
/**
@ -199,4 +214,9 @@ public class WorldBorder {
private void sendPacket(WorldBorderPacket worldBorderPacket) {
instance.getPlayers().forEach(player -> player.getPlayerConnection().sendPacket(worldBorderPacket));
}
public enum CollisionAxis {
X, Z, BOTH, NONE
}
}