Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
Expand Down Expand Up @@ -88,6 +90,12 @@ public class SessionPlayerEntity extends PlayerEntity {

private int lastAirSupply = getMaxAir();

/**
* The client last tick end velocity, used for calculating player onGround.
*/
@Getter @Setter
private Vector3f lastTickEndVelocity = Vector3f.ZERO;

/**
* Determines if our position is currently out-of-sync with the Java server
* due to our workaround for the void floor
Expand Down Expand Up @@ -407,4 +415,17 @@ public void teleportVoidFloorFix(boolean up) {
movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR);
session.sendUpstreamPacketImmediately(movePlayerPacket);
}

/**
* Used to calculate player jumping velocity for ground status calculation.
*/
public float getJumpVelocity() {
float velocity = 0.42F;

if (session.getGeyser().getWorldManager().blockAt(session, this.getPosition().sub(0, EntityDefinitions.PLAYER.offset() + 0.1F, 0).toInt()).is(Blocks.HONEY_BLOCK)) {
velocity *= 0.6F;
}

return velocity + 0.1F * session.getEffectCache().getJumpPower();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ public class EntityEffectCache {
@Getter
private int miningFatigue;

/* Used to calculate jumping velocity */
@Getter
private int jumpPower;

public void setEffect(Effect effect, int effectAmplifier) {
switch (effect) {
case CONDUIT_POWER -> conduitPower = effectAmplifier + 1;
case HASTE -> haste = effectAmplifier + 1;
case MINING_FATIGUE -> miningFatigue = effectAmplifier + 1;
case JUMP_BOOST -> jumpPower = effectAmplifier + 1;
}
entityEffects.add(effect);
}
Expand All @@ -60,6 +65,7 @@ public void removeEffect(Effect effect) {
case CONDUIT_POWER -> conduitPower = 0;
case HASTE -> haste = 0;
case MINING_FATIGUE -> miningFatigue = 0;
case JUMP_BOOST -> jumpPower = 0;
}
entityEffects.remove(effect);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.level.physics.CollisionResult;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.BlockTag;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
Expand Down Expand Up @@ -86,15 +87,28 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
session.setLookBackScheduledFuture(null);
}

// Simulate jumping since it happened this tick, not from the last tick end.
if (entity.isOnGround() && packet.getInputData().contains(PlayerAuthInputData.START_JUMPING)) {
entity.setLastTickEndVelocity(Vector3f.from(entity.getLastTickEndVelocity().getX(), Math.max(entity.getLastTickEndVelocity().getY(), entity.getJumpVelocity()), entity.getLastTickEndVelocity().getZ()));
}

// Due to how ladder works on Bedrock, we won't get climbing velocity from tick end unless if you're colliding horizontally. So we account for it ourselves.
boolean onClimbableBlock = session.getTagCache().is(BlockTag.CLIMBABLE, session.getGeyser().getWorldManager().blockAt(session, entity.getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0).toInt()).block());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen here if a block is marked as climbable, but isn't on Bedrock?

@Oryxel Oryxel Apr 12, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that will actually happen, but if it were to happened I guess I can remove the horizontalCollision part
since it is not needed in this case anyway and it should be fine since the player is "jumping" or atleast pressing jump so it will prob still correct.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that will actually happen, but if it were to happened I guess I can remove the horizontalCollision part since it is not needed in this case anyway and it should be fine since the player is "jumping" or atleast pressing jump so it will prob still correct.

Impressive work there Oryxel, would any of this issue also apply to when players are mounted on a horse and jumping it? We've long had an issue where Bedrock players outperform Java players when they are racing on horses.

if (onClimbableBlock && packet.getInputData().contains(PlayerAuthInputData.JUMPING)) {
entity.setLastTickEndVelocity(Vector3f.from(entity.getLastTickEndVelocity().getX(), 0.2F, entity.getLastTickEndVelocity().getZ()));
}

// Client is telling us it wants to move down, but something is blocking it from doing so.
boolean isOnGround;
if (hasVehicle) {
// VERTICAL_COLLISION is not accurate while in a vehicle (as of 1.21.62)
isOnGround = Math.abs(packet.getDelta().getY()) < 0.1;
isOnGround = Math.abs(entity.getLastTickEndVelocity().getY()) < 0.1;
} else {
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && entity.getLastTickEndVelocity().getY() < 0;
}

entity.setLastTickEndVelocity(packet.getDelta());

// 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)
// This isn't sent when a player is riding a vehicle (as of 1.21.62)
Expand Down