Skip to content
Open
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
84 changes: 84 additions & 0 deletions core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
package org.geysermc.geyser.entity.type;

import lombok.Getter;
import org.cloudburstmc.math.GenericMath;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.vehicle.BoatVehicleComponent;
Expand All @@ -39,6 +41,7 @@
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.MathUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
Expand Down Expand Up @@ -76,6 +79,10 @@ public class BoatEntity extends Entity implements Tickable, Leashable, ClientVeh
// This is the best value, I can't really found any value that doesn't look choppy and laggy or that is not too slow, blame bedrock.
private final float ROWING_SPEED = 0.04f;

private Vector3f lerpPosition;
private float lerpYaw, lerpHeadYaw;
private int lerpSteps;

public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) {
// Initial rotation is incorrect
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
Expand Down Expand Up @@ -125,6 +132,36 @@ public void moveAbsoluteWithoutAdjustments(Vector3f position, float yaw, boolean
super.moveAbsoluteRaw(position, yaw, 0, yaw, isOnGround, teleported);
}

@Override
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
this.lerpYaw = yaw + 90;
this.lerpHeadYaw = headYaw + 90;

if ((relX != 0 || relY != 0 || relZ != 0) && position.distanceSquared(session.getPlayerEntity().position()) < 4096) {
setPitch(0);
this.lerpPosition = Vector3f.from(lerpPosition.getX() + relX, lerpPosition.getY() + relY, lerpPosition.getZ() + relZ);
this.lerpSteps = 3;
} else {
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
}
}

@Override
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
this.lerpPosition = position;
this.lerpYaw = yaw + 90;
this.lerpHeadYaw = headYaw + 90;

// It's vanilla behaviour to lerp if the position is within 64 blocks, however we also check if the position is close enough to the player
// position to see if it can actually affect anything to save network.
if (position.distanceSquared(this.position) < 4096 && position.distanceSquared(session.getPlayerEntity().position()) < 4096) {
setPitch(0);
this.lerpSteps = 3;
} else {
super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
}
}

@Override
public void moveRelativeRaw(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
super.moveRelativeRaw(relX, relY, relZ, yaw, 0, yaw, isOnGround);
Expand Down Expand Up @@ -193,6 +230,53 @@ public InteractionResult interact(Hand hand) {

@Override
public void tick() {
if (this.lerpSteps > 0) {
float time = 1.0f / this.lerpSteps;
float lerpXTotal = GenericMath.lerp(this.position.getX(), this.lerpPosition.getX(), time);
float lerpYTotal = GenericMath.lerp(this.position.getY() - this.definition.offset(), this.lerpPosition.getY(), time) + this.definition.offset();
float lerpZTotal = GenericMath.lerp(this.position.getZ(), this.lerpPosition.getZ(), time);
float lerpYaw = MathUtils.rotLerp(this.yaw, this.lerpYaw, time);
float lerpHeadYaw = MathUtils.rotLerp(this.headYaw, this.lerpHeadYaw, time);

MoveEntityDeltaPacket moveEntityPacket = new MoveEntityDeltaPacket();
moveEntityPacket.setRuntimeEntityId(geyserId);
moveEntityPacket.setX(lerpXTotal);
moveEntityPacket.setY(lerpYTotal);
moveEntityPacket.setZ(lerpZTotal);
moveEntityPacket.setYaw(lerpYaw);
moveEntityPacket.setPitch(this.pitch);
moveEntityPacket.setHeadYaw(lerpHeadYaw);
if (onGround) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND);
}
if (lerpXTotal != this.position.getX()) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X);
}
if (lerpYTotal != this.position.getY()) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Y);
}
if (lerpZTotal != this.position.getZ()) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Z);
}
if (lerpYaw != this.yaw) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
}
if (lerpHeadYaw != this.headYaw) {
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
}
moveEntityPacket.getFlags().add(MoveEntityDeltaPacket.Flag.TELEPORTING);

// Queue this and send it immediately later with the rest.
session.getQueuedImmediatelyPackets().add(moveEntityPacket);

this.position = Vector3f.from(lerpXTotal, lerpYTotal, lerpZTotal);
this.yaw = lerpYaw;
this.headYaw = lerpHeadYaw;
this.lerpSteps--;

vehicleComponent.moveAbsolute(lerpXTotal, lerpYTotal, lerpZTotal);
}

// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
if (session.getPlayerEntity().getVehicle() == this) {
// For packet timing accuracy, we'll send the packets here, as that's what Java Edition 1.21.3 does.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ public void tick() {

this.position = Vector3f.from(lerpXTotal, lerpYTotal, lerpZTotal);
this.lerpSteps--;

if (this instanceof ClientVehicle vehicle) {
vehicle.getVehicleComponent().moveAbsolute(lerpXTotal, lerpYTotal, lerpZTotal);
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/org/geysermc/geyser/util/MathUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public static Vector3f calculateViewVector(float pitch, float yaw) {
return Vector3f.from(var6 * var7, -var8, var5 * var7);
}

public static float rotLerp(float var1, float var2, float var0) {
return var1 + var0 * wrapDegrees(var2 - var1);
}

/**
* Wrap the given float degrees to be between -180.0 and 180.0.
*
Expand Down