1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-22 16:29:25 +00:00

More accurate ground status translation (#5481)

This commit is contained in:
Oryxel
2025-04-13 17:47:19 +07:00
committed by GitHub
parent 6edcbe9dd2
commit 23a462d60c
3 changed files with 43 additions and 2 deletions

View File

@@ -36,9 +36,11 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
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;
@@ -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
@@ -407,4 +415,17 @@ public class SessionPlayerEntity extends PlayerEntity {
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();
}
}

View File

@@ -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);
}
@@ -60,6 +65,7 @@ public class EntityEffectCache {
case CONDUIT_POWER -> conduitPower = 0;
case HASTE -> haste = 0;
case MINING_FATIGUE -> miningFatigue = 0;
case JUMP_BOOST -> jumpPower = 0;
}
entityEffects.remove(effect);
}

View File

@@ -33,6 +33,7 @@ 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.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;
@@ -86,15 +87,28 @@ final class BedrockMovePlayer {
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());
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)