1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-23 08:49:23 +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.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
@@ -88,6 +90,12 @@ public class SessionPlayerEntity extends PlayerEntity {
private int lastAirSupply = getMaxAir(); 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 * Determines if our position is currently out-of-sync with the Java server
* due to our workaround for the void floor * due to our workaround for the void floor
@@ -407,4 +415,17 @@ public class SessionPlayerEntity extends PlayerEntity {
movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR); movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR);
session.sendUpstreamPacketImmediately(movePlayerPacket); 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 @Getter
private int miningFatigue; private int miningFatigue;
/* Used to calculate jumping velocity */
@Getter
private int jumpPower;
public void setEffect(Effect effect, int effectAmplifier) { public void setEffect(Effect effect, int effectAmplifier) {
switch (effect) { switch (effect) {
case CONDUIT_POWER -> conduitPower = effectAmplifier + 1; case CONDUIT_POWER -> conduitPower = effectAmplifier + 1;
case HASTE -> haste = effectAmplifier + 1; case HASTE -> haste = effectAmplifier + 1;
case MINING_FATIGUE -> miningFatigue = effectAmplifier + 1; case MINING_FATIGUE -> miningFatigue = effectAmplifier + 1;
case JUMP_BOOST -> jumpPower = effectAmplifier + 1;
} }
entityEffects.add(effect); entityEffects.add(effect);
} }
@@ -60,6 +65,7 @@ public class EntityEffectCache {
case CONDUIT_POWER -> conduitPower = 0; case CONDUIT_POWER -> conduitPower = 0;
case HASTE -> haste = 0; case HASTE -> haste = 0;
case MINING_FATIGUE -> miningFatigue = 0; case MINING_FATIGUE -> miningFatigue = 0;
case JUMP_BOOST -> jumpPower = 0;
} }
entityEffects.remove(effect); 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.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.level.physics.CollisionResult; import org.geysermc.geyser.level.physics.CollisionResult;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.BlockTag;
import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.ChatColor;
import org.geysermc.mcprotocollib.network.packet.Packet; import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
@@ -86,15 +87,28 @@ final class BedrockMovePlayer {
session.setLookBackScheduledFuture(null); 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. // Client is telling us it wants to move down, but something is blocking it from doing so.
boolean isOnGround; boolean isOnGround;
if (hasVehicle) { if (hasVehicle) {
// VERTICAL_COLLISION is not accurate while in a vehicle (as of 1.21.62) // 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 { } 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. // 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) // (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) // This isn't sent when a player is riding a vehicle (as of 1.21.62)