feat(net): plumb IsGrounded through EntityPositionUpdate (L.3.2 Task 2)

PositionFlags.IsGrounded (0x04) was already parsed by UpdatePosition
but not exposed through the Parsed record or EntityPositionUpdate.
Adds the bool field to both records so OnLivePositionUpdated can
consume it for retail-faithful MoveOrTeleport routing
(acclient @ 0x00516330: has_contact=false → no-op during airborne arc).

Consumed in subsequent task (L.3.1+L.3.2 Task 3).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-03 10:15:02 +02:00
parent 08fbbef3c4
commit 5d717312cc
2 changed files with 6 additions and 2 deletions

View file

@ -64,6 +64,7 @@ public static class UpdatePosition
CreateObject.ServerPosition Position,
System.Numerics.Vector3? Velocity,
uint? PlacementId,
bool IsGrounded,
ushort InstanceSequence = 0,
ushort TeleportSequence = 0,
ushort ForcePositionSequence = 0);
@ -164,6 +165,7 @@ public static class UpdatePosition
RotationW: rw, RotationX: rx, RotationY: ry, RotationZ: rz);
return new Parsed(guid, serverPos, velocity, placementId,
IsGrounded: (flags & PositionFlags.IsGrounded) != 0,
instSeq, teleSeq, forceSeq);
}
catch

View file

@ -110,7 +110,8 @@ public sealed class WorldSession : IDisposable
public readonly record struct EntityPositionUpdate(
uint Guid,
CreateObject.ServerPosition Position,
System.Numerics.Vector3? Velocity);
System.Numerics.Vector3? Velocity,
bool IsGrounded);
/// <summary>
/// Fires when the session parses a 0xF748 UpdatePosition game message.
@ -711,7 +712,8 @@ public sealed class WorldSession : IDisposable
PositionUpdated?.Invoke(new EntityPositionUpdate(
posUpdate.Value.Guid,
posUpdate.Value.Position,
posUpdate.Value.Velocity));
posUpdate.Value.Velocity,
posUpdate.Value.IsGrounded));
}
}
else if (op == VectorUpdate.Opcode)