Update player bounding box in more scenarios (#2377)

Co-authored-by: Camotoy <20743703+Camotoy@users.noreply.github.com>
This commit is contained in:
David Choo 2021-07-18 10:58:08 -04:00 committed by GitHub
parent 4e629feee8
commit 2766038db9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 106 deletions

View file

@ -155,10 +155,6 @@ public class PlayerEntity extends LivingEntity {
setRotation(rotation);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
// If this is the player logged in through this Geyser session
if (geyserId == 1) {
session.getCollisionManager().updatePlayerBoundingBox(position);
}
setOnGround(isOnGround);
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
@ -230,18 +226,7 @@ public class PlayerEntity extends LivingEntity {
@Override
public void setPosition(Vector3f position) {
setPosition(position, true);
}
/**
* Set the player position and specify if the entity type's offset should be added. Set to false when the player
* sends us a move packet where the offset is already added
*
* @param position the new position of the Bedrock player
* @param includeOffset whether to include the offset
*/
public void setPosition(Vector3f position, boolean includeOffset) {
this.position = includeOffset ? position.add(0, entityType.getOffset(), 0) : position;
super.setPosition(position.add(0, entityType.getOffset(), 0));
}
@Override

View file

@ -74,9 +74,9 @@ public class SessionPlayerEntity extends PlayerEntity {
}
@Override
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
session.getCollisionManager().updatePlayerBoundingBox(position);
super.moveAbsolute(session, position, rotation, isOnGround, teleported);
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
session.getCollisionManager().updatePlayerBoundingBox(this.position.down(entityType.getOffset()));
}
@Override
@ -87,6 +87,17 @@ public class SessionPlayerEntity extends PlayerEntity {
super.setPosition(position);
}
/**
* Set the player's position without applying an offset or moving the bounding box
* This is used in BedrockMovePlayerTranslator which receives the player's position
* with the offset pre-applied
*
* @param position the new position of the Bedrock player
*/
public void setPositionManual(Vector3f position) {
this.position = position;
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
super.updateBedrockMetadata(entityMetadata, session);

View file

@ -1132,9 +1132,9 @@ public class GeyserSession implements CommandSender {
}
}
public boolean confirmTeleport(Vector3d position) {
public void confirmTeleport(Vector3d position) {
if (teleportMap.size() == 0) {
return true;
return;
}
int teleportID = -1;
@ -1185,8 +1185,6 @@ public class GeyserSession implements CommandSender {
teleport.getYaw(), teleport.getPitch(), playerEntity.isOnGround(), true);
}
}
return true;
}
/**

View file

@ -35,7 +35,7 @@ import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.entity.player.PlayerEntity;
import org.geysermc.connector.entity.player.SessionPlayerEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -54,7 +54,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
@Override
public void translate(MovePlayerPacket packet, GeyserSession session) {
PlayerEntity entity = session.getPlayerEntity();
SessionPlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned()) return;
if (!session.getUpstream().isInitialized()) {
@ -73,7 +73,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
// Send book update before the player moves
session.getBookEditCache().checkForSend();
if (session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityType.PLAYER.getOffset(), 0))) {
session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityType.PLAYER.getOffset(), 0));
// head yaw, pitch, head yaw
Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
@ -109,7 +109,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
// Compare positions here for void floor fix below before the player's position variable is set to the packet position
boolean notMovingUp = entity.getPosition().getY() >= packet.getPosition().getY();
entity.setPosition(packet.getPosition(), false);
entity.setPositionManual(packet.getPosition());
entity.setOnGround(packet.isOnGround());
// Send final movement changes
@ -141,7 +141,6 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
}
}
}
}
// Move parrots to match if applicable
if (entity.getLeftParrot() != null) {

View file

@ -54,7 +54,7 @@ public class CollisionManager {
private final GeyserSession session;
@Getter
private BoundingBox playerBoundingBox;
private final BoundingBox playerBoundingBox;
/**
* Whether the player is inside scaffolding
@ -105,26 +105,16 @@ public class CollisionManager {
}
/**
* Updates the stored bounding box without passing a position, which currently just changes the height depending on if the player is sneaking.
* Updates the height of the stored bounding box
*/
public void updatePlayerBoundingBox() {
if (playerBoundingBox == null) {
Vector3f playerPosition;
if (session.getPlayerEntity() == null) {
// Temporary position to prevent NullPointerException
playerPosition = Vector3f.ZERO;
} else {
playerPosition = session.getPlayerEntity().getPosition();
}
playerBoundingBox = new BoundingBox(playerPosition.getX(), playerPosition.getY() + 0.9, playerPosition.getZ(),
EntityType.PLAYER.getWidth(), EntityType.PLAYER.getHeight(), EntityType.PLAYER.getLength());
} else {
// According to the Minecraft Wiki, when sneaking:
// - In Bedrock Edition, the height becomes 1.65 blocks, allowing movement through spaces as small as 1.75 (2 - 14) blocks high.
// - In Java Edition, the height becomes 1.5 blocks.
// Other instances have the player's bounding box become as small as 0.6 or 0.2.
playerBoundingBox.setSizeY(session.getPlayerEntity().getMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT));
}
double playerHeight = session.getPlayerEntity().getMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT);
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() - (playerBoundingBox.getSizeY() / 2.0) + (playerHeight / 2.0));
playerBoundingBox.setSizeY(playerHeight);
}
/**
@ -265,9 +255,15 @@ public class CollisionManager {
if (collision != null) {
// Determine, if the player's bounding box *were* at full height, if it would intersect with the block
// at the current location.
double originalY = playerBoundingBox.getMiddleY();
double originalHeight = playerBoundingBox.getSizeY();
double standingY = originalY - (originalHeight / 2.0) + (EntityType.PLAYER.getHeight() / 2.0);
playerBoundingBox.setSizeY(EntityType.PLAYER.getHeight());
playerBoundingBox.setMiddleY(standingY);
boolean result = collision.checkIntersection(playerBoundingBox);
playerBoundingBox.setSizeY(session.getPlayerEntity().getMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT));
playerBoundingBox.setSizeY(originalHeight);
playerBoundingBox.setMiddleY(originalY);
return result;
}
return false;

View file

@ -124,8 +124,18 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
session.getConnector().getLogger().debug("Teleport from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityType.PLAYER.getOffset()) + " " + entity.getPosition().getZ());
session.addTeleport(new TeleportCache(newX, newY, newZ, newPitch, newYaw, packet.getTeleportId()));
entity.moveAbsolute(session, Vector3f.from(newX, newY, newZ), newYaw, newPitch, true, true);
Vector3f lastPlayerPosition = entity.getPosition().down(EntityType.PLAYER.getOffset());
float lastPlayerPitch = entity.getBedrockRotation().getX();
Vector3f teleportDestination = Vector3f.from(newX, newY, newZ);
entity.moveAbsolute(session, teleportDestination, newYaw, newPitch, true, true);
session.getConnector().getLogger().debug("to " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityType.PLAYER.getOffset()) + " " + entity.getPosition().getZ());
// Bedrock ignores teleports that are extremely close to the player's original position and orientation,
// so check if we can immediately confirm the teleport
if (lastPlayerPosition.distanceSquared(teleportDestination) < 0.001 && Math.abs(newPitch - lastPlayerPitch) < 5) {
session.confirmTeleport(lastPlayerPosition.toDouble());
}
}
}