Skip to content

Commit 23a462d

Browse files
authored
More accurate ground status translation (#5481)
1 parent 6edcbe9 commit 23a462d

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
3737
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
3838
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
39+
import org.geysermc.geyser.entity.EntityDefinitions;
3940
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
4041
import org.geysermc.geyser.item.Items;
4142
import org.geysermc.geyser.level.BedrockDimension;
43+
import org.geysermc.geyser.level.block.Blocks;
4244
import org.geysermc.geyser.session.GeyserSession;
4345
import org.geysermc.geyser.util.AttributeUtils;
4446
import org.geysermc.geyser.util.DimensionUtils;
@@ -88,6 +90,12 @@ public class SessionPlayerEntity extends PlayerEntity {
8890

8991
private int lastAirSupply = getMaxAir();
9092

93+
/**
94+
* The client last tick end velocity, used for calculating player onGround.
95+
*/
96+
@Getter @Setter
97+
private Vector3f lastTickEndVelocity = Vector3f.ZERO;
98+
9199
/**
92100
* Determines if our position is currently out-of-sync with the Java server
93101
* due to our workaround for the void floor
@@ -407,4 +415,17 @@ public void teleportVoidFloorFix(boolean up) {
407415
movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR);
408416
session.sendUpstreamPacketImmediately(movePlayerPacket);
409417
}
418+
419+
/**
420+
* Used to calculate player jumping velocity for ground status calculation.
421+
*/
422+
public float getJumpVelocity() {
423+
float velocity = 0.42F;
424+
425+
if (session.getGeyser().getWorldManager().blockAt(session, this.getPosition().sub(0, EntityDefinitions.PLAYER.offset() + 0.1F, 0).toInt()).is(Blocks.HONEY_BLOCK)) {
426+
velocity *= 0.6F;
427+
}
428+
429+
return velocity + 0.1F * session.getEffectCache().getJumpPower();
430+
}
410431
}

core/src/main/java/org/geysermc/geyser/session/cache/EntityEffectCache.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ public class EntityEffectCache {
4646
@Getter
4747
private int miningFatigue;
4848

49+
/* Used to calculate jumping velocity */
50+
@Getter
51+
private int jumpPower;
52+
4953
public void setEffect(Effect effect, int effectAmplifier) {
5054
switch (effect) {
5155
case CONDUIT_POWER -> conduitPower = effectAmplifier + 1;
5256
case HASTE -> haste = effectAmplifier + 1;
5357
case MINING_FATIGUE -> miningFatigue = effectAmplifier + 1;
58+
case JUMP_BOOST -> jumpPower = effectAmplifier + 1;
5459
}
5560
entityEffects.add(effect);
5661
}
@@ -60,6 +65,7 @@ public void removeEffect(Effect effect) {
6065
case CONDUIT_POWER -> conduitPower = 0;
6166
case HASTE -> haste = 0;
6267
case MINING_FATIGUE -> miningFatigue = 0;
68+
case JUMP_BOOST -> jumpPower = 0;
6369
}
6470
entityEffects.remove(effect);
6571
}

core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockMovePlayer.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
3434
import org.geysermc.geyser.level.physics.CollisionResult;
3535
import org.geysermc.geyser.session.GeyserSession;
36+
import org.geysermc.geyser.session.cache.tags.BlockTag;
3637
import org.geysermc.geyser.text.ChatColor;
3738
import org.geysermc.mcprotocollib.network.packet.Packet;
3839
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
@@ -86,15 +87,28 @@ static void translate(GeyserSession session, PlayerAuthInputPacket packet) {
8687
session.setLookBackScheduledFuture(null);
8788
}
8889

90+
// Simulate jumping since it happened this tick, not from the last tick end.
91+
if (entity.isOnGround() && packet.getInputData().contains(PlayerAuthInputData.START_JUMPING)) {
92+
entity.setLastTickEndVelocity(Vector3f.from(entity.getLastTickEndVelocity().getX(), Math.max(entity.getLastTickEndVelocity().getY(), entity.getJumpVelocity()), entity.getLastTickEndVelocity().getZ()));
93+
}
94+
95+
// 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.
96+
boolean onClimbableBlock = session.getTagCache().is(BlockTag.CLIMBABLE, session.getGeyser().getWorldManager().blockAt(session, entity.getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0).toInt()).block());
97+
if (onClimbableBlock && packet.getInputData().contains(PlayerAuthInputData.JUMPING)) {
98+
entity.setLastTickEndVelocity(Vector3f.from(entity.getLastTickEndVelocity().getX(), 0.2F, entity.getLastTickEndVelocity().getZ()));
99+
}
100+
89101
// Client is telling us it wants to move down, but something is blocking it from doing so.
90102
boolean isOnGround;
91103
if (hasVehicle) {
92104
// VERTICAL_COLLISION is not accurate while in a vehicle (as of 1.21.62)
93-
isOnGround = Math.abs(packet.getDelta().getY()) < 0.1;
105+
isOnGround = Math.abs(entity.getLastTickEndVelocity().getY()) < 0.1;
94106
} else {
95-
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && packet.getDelta().getY() < 0;
107+
isOnGround = packet.getInputData().contains(PlayerAuthInputData.VERTICAL_COLLISION) && entity.getLastTickEndVelocity().getY() < 0;
96108
}
97109

110+
entity.setLastTickEndVelocity(packet.getDelta());
111+
98112
// This takes into account no movement sent from the client, but the player is trying to move anyway.
99113
// (Press into a wall in a corner - you're trying to move but nothing actually happens)
100114
// This isn't sent when a player is riding a vehicle (as of 1.21.62)

0 commit comments

Comments
 (0)