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:
Ursprung
aebf9d399b
Commit
1b4d257e35
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren