Fix REntity position desync and velocity in 1.21 replays

Send ClientboundEntityPositionSyncPacket instead of the teleport packet so
relative moves keep working afterwards, and pass rotation in degrees.
Pass the velocity unscaled to Vec3 instead of pre-multiplying by 8000.
Fixes #247
This commit is contained in:
2026-10-19 09:03:52 +02:00
parent 69aef9dfb6
commit 380693a2b7
@@ -180,7 +180,7 @@ public class REntity {
} }
public void setVelocity(double dX, double dY, double dZ) { public void setVelocity(double dX, double dY, double dZ) {
server.updateEntity(this, new ClientboundSetEntityMotionPacket(entityId, new Vec3(calcVelocity(dX), calcVelocity(dY), calcVelocity(dZ)))); server.updateEntity(this, new ClientboundSetEntityMotionPacket(entityId, new Vec3(dX, dY, dZ)));
} }
public void showDamage() { public void showDamage() {
@@ -340,8 +340,8 @@ public class REntity {
} }
private Object getTeleportPacket() { private Object getTeleportPacket() {
PositionMoveRotation rot = new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, pitch, yaw); PositionMoveRotation rot = new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, pitch * 360F / 256F, yaw * 360F / 256F);
return new ClientboundTeleportEntityPacket(entityId, rot, Collections.emptySet(), false); return new ClientboundEntityPositionSyncPacket(entityId, rot, false);
} }
private Object getMoveLookPacket(double diffX, double diffY, double diffZ, boolean rotEq) { private Object getMoveLookPacket(double diffX, double diffY, double diffZ, boolean rotEq) {
@@ -387,10 +387,6 @@ public class REntity {
return (byte) ((int) (rot * 256.0F / 360.0F)); return (byte) ((int) (rot * 256.0F / 360.0F));
} }
private int calcVelocity(double value) {
return (int) (Math.max(-3.9, Math.min(value, 3.9)) * 8000);
}
private static Optional<Component> formatDisplayName(String displayName) { private static Optional<Component> formatDisplayName(String displayName) {
return displayName != null ? Optional.of(MutableComponent.create(PlainTextContents.create(displayName))) : Optional.empty(); return displayName != null ? Optional.of(MutableComponent.create(PlainTextContents.create(displayName))) : Optional.empty();
} }