3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-26 00:00:41 +01:00

Better onGround check

Thanks to @AJ-Ferguson for the suggestion.

Includes hacks to still maintain pre-1.21.30, but that will likely lose support very soon, anyway.
Dieser Commit ist enthalten in:
Camotoy 2024-11-07 16:09:31 -05:00
Ursprung aebf9d399b
Commit 1b4d257e35
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
3 geänderte Dateien mit 27 neuen und 12 gelöschten Zeilen

Datei anzeigen

@ -154,10 +154,11 @@ public class CollisionManager {
* the two versions. Will also send corrected movement packets back to Bedrock if they collide with pistons.
*
* @param bedrockPosition the current Bedrock position of the client
* @param onGround whether the Bedrock player is on the ground
* @param teleported whether the Bedrock player has teleported to a new position. If true, movement correction is skipped.
* @return the position to send to the Java server, or null to cancel sending the packet
*/
public @Nullable CollisionResult adjustBedrockPosition(Vector3f bedrockPosition, boolean teleported) {
public @Nullable CollisionResult adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) {
PistonCache pistonCache = session.getPistonCache();
// Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position
if (pistonCache.isPlayerAttachedToHoney()) {
@ -198,9 +199,9 @@ public class CollisionManager {
position = playerBoundingBox.getBottomCenter();
boolean onGround = (adjustedMovement.getY() != movement.getY() && movement.getY() < 0) || isOnGround();
boolean newOnGround = adjustedMovement.getY() != movement.getY() && movement.getY() < 0 || onGround;
// Send corrected position to Bedrock if they differ by too much to prevent de-syncs
if (movement.distanceSquared(adjustedMovement) > INCORRECT_MOVEMENT_THRESHOLD) {
if (onGround != newOnGround || movement.distanceSquared(adjustedMovement) > INCORRECT_MOVEMENT_THRESHOLD) {
PlayerEntity playerEntity = session.getPlayerEntity();
// Client will dismount if on a vehicle
if (playerEntity.getVehicle() == null && pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) {
@ -208,7 +209,7 @@ public class CollisionManager {
}
}
if (!onGround) {
if (!newOnGround) {
// Trim the position to prevent rounding errors that make Java think we are clipping into a block
position = Vector3d.from(position.getX(), Double.parseDouble(DECIMAL_FORMAT.format(position.getY())), position.getZ());
}
@ -415,8 +416,8 @@ public class CollisionManager {
return BlockUtils.getCollision(blockId);
}
private boolean isOnGround() {
// Someone smarter than me at collisions plz check this.
public boolean isOnGround() {
// Temporary until pre-1.21.30 support is dropped.
Vector3d bottomCenter = playerBoundingBox.getBottomCenter();
Vector3i groundPos = Vector3i.from(bottomCenter.getX(), bottomCenter.getY() - 1, bottomCenter.getZ());
BlockCollision collision = BlockUtils.getCollisionAt(session, groundPos);

Datei anzeigen

@ -111,6 +111,10 @@ public final class GameProtocol {
return session.getUpstream().getProtocolVersion() < Bedrock_v686.CODEC.getProtocolVersion();
}
public static boolean isPre1_21_30(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v729.CODEC.getProtocolVersion();
}
public static boolean isPre1_21_40(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v748.CODEC.getProtocolVersion();
}

Datei anzeigen

@ -25,6 +25,7 @@
package org.geysermc.geyser.translator.protocol.bedrock.entity.player.input;
import net.kyori.adventure.util.TriState;
import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.PlayerAuthInputData;
@ -32,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.level.physics.CollisionResult;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.mcprotocollib.network.packet.Packet;
@ -86,6 +88,14 @@ final class BedrockMovePlayer {
session.setLookBackScheduledFuture(null);
}
TriState maybeOnGround;
if (GameProtocol.isPre1_21_30(session)) {
// VERTICAL_COLLISION input data does not exist.
maybeOnGround = TriState.NOT_SET;
} else {
// Client is telling us it wants to move down, but something is blocking it from doing so.
maybeOnGround = TriState.byBoolean(packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0);
}
// This takes into account no movement sent from the client, but the player is trying to move anyway.
// (Press into a wall in a corner - you're trying to move but nothing actually happens)
boolean horizontalCollision = packet.getInputData().contains(PlayerAuthInputData.HORIZONTAL_COLLISION);
@ -94,7 +104,7 @@ final class BedrockMovePlayer {
// This isn't needed, but it makes the packets closer to vanilla
// It also means you can't "lag back" while only looking, in theory
if (!positionChanged && rotationChanged) {
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(entity.isOnGround(), horizontalCollision, yaw, pitch);
ServerboundMovePlayerRotPacket playerRotationPacket = new ServerboundMovePlayerRotPacket(maybeOnGround.toBooleanOrElse(entity.isOnGround()), horizontalCollision, yaw, pitch);
entity.setYaw(yaw);
entity.setPitch(pitch);
@ -103,10 +113,10 @@ final class BedrockMovePlayer {
session.sendDownstreamGamePacket(playerRotationPacket);
} else if (positionChanged) {
if (isValidMove(session, entity.getPosition(), packet.getPosition())) {
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
CollisionResult result = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), maybeOnGround.toBooleanOrElse(false), packet.getInputData().contains(PlayerAuthInputData.HANDLE_TELEPORT));
if (result != null) { // A null return value cancels the packet
Vector3d position = result.correctedMovement();
boolean onGround = result.onGround().toBooleanOrElse(entity.isOnGround());
boolean onGround = maybeOnGround.toBooleanOrElseGet(() -> session.getCollisionManager().isOnGround());
boolean isBelowVoid = entity.isVoidPositionDesynched();
boolean teleportThroughVoidFloor, mustResyncPosition;
@ -155,7 +165,6 @@ final class BedrockMovePlayer {
}
entity.setPositionManual(packet.getPosition());
entity.setOnGround(onGround);
// Send final movement changes
session.sendDownstreamGamePacket(movePacket);
@ -174,11 +183,12 @@ final class BedrockMovePlayer {
session.getGeyser().getLogger().debug("Recalculating position...");
session.getCollisionManager().recalculatePosition();
}
} else if (horizontalCollision != session.getInputCache().lastHorizontalCollision()) {
session.sendDownstreamGamePacket(new ServerboundMovePlayerStatusOnlyPacket(entity.isOnGround(), horizontalCollision));
} else if (horizontalCollision != session.getInputCache().lastHorizontalCollision() || maybeOnGround.toBooleanOrElse(entity.isOnGround()) != entity.isOnGround()) {
session.sendDownstreamGamePacket(new ServerboundMovePlayerStatusOnlyPacket(maybeOnGround.toBooleanOrElse(false), horizontalCollision));
}
session.getInputCache().setLastHorizontalCollision(horizontalCollision);
entity.setOnGround(maybeOnGround.toBooleanOrElse(entity.isOnGround()));
// Move parrots to match if applicable
if (entity.getLeftParrot() != null) {