feat(net): Phase 6.6 — parse UpdateMotion (0xF74C) into MotionUpdated event
Server sends UpdateMotion whenever an entity's motion state changes: NPCs starting a walk cycle, creatures switching to a combat stance, doors opening, a player waving, etc. Phase 6.1-6.4 already handles rendering different (stance, forward-command) pairs for the INITIAL CreateObject, but without this message NPCs freeze in whatever pose they spawned with and never transition to walking/fighting. Added UpdateMotion.TryParse with the same ServerMotionState the CreateObject path uses, reached via a slightly different outer layout (guid + instance seq + header'd MovementData; the MovementData starts with the 8-byte sequence/autonomous header this time rather than being preceded by a length field). Only the (stance, forward- command) pair is extracted — same subset CreateObject grabs. WorldSession dispatches MotionUpdated(guid, state) when a 0xF74C body parses successfully. The App-side wiring (guid→entity lookup and AnimatedEntity cycle swap) is intentionally deferred to a separate commit because it touches GameWindow which is currently being edited by the Phase 9.1 translucent-pass work. 89 Core.Net tests (was 83, +6 for UpdateMotion coverage). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4752b8a528
commit
a71db90310
12 changed files with 675 additions and 45 deletions
|
|
@ -58,6 +58,22 @@ public sealed class WorldSession : IDisposable
|
|||
/// <summary>Fires when the session finishes parsing a CreateObject.</summary>
|
||||
public event Action<EntitySpawn>? EntitySpawned;
|
||||
|
||||
/// <summary>
|
||||
/// Payload for <see cref="MotionUpdated"/>: the server guid of the entity
|
||||
/// whose motion changed and its new server-side stance + forward command.
|
||||
/// The renderer uses these to drive per-entity cycle switching.
|
||||
/// </summary>
|
||||
public readonly record struct EntityMotionUpdate(
|
||||
uint Guid,
|
||||
CreateObject.ServerMotionState MotionState);
|
||||
|
||||
/// <summary>
|
||||
/// Fires when the session parses a 0xF74C UpdateMotion game message.
|
||||
/// Subscribers can look up the entity by guid and transition its
|
||||
/// animation cycle to the new (stance, forward-command) pair.
|
||||
/// </summary>
|
||||
public event Action<EntityMotionUpdate>? MotionUpdated;
|
||||
|
||||
/// <summary>Raised every time the state machine transitions.</summary>
|
||||
public event Action<State>? StateChanged;
|
||||
|
||||
|
|
@ -243,6 +259,22 @@ public sealed class WorldSession : IDisposable
|
|||
parsed.Value.MotionTableId));
|
||||
}
|
||||
}
|
||||
else if (op == UpdateMotion.Opcode)
|
||||
{
|
||||
// Phase 6.6: the server sends UpdateMotion (0xF74C) whenever an
|
||||
// already-spawned entity changes its motion state — NPCs
|
||||
// starting a walk cycle, creatures entering combat, doors
|
||||
// opening, etc. We dispatch a lightweight event with the
|
||||
// new (stance, forward-command) pair so the animation
|
||||
// system can swap the entity's cycle.
|
||||
var motion = UpdateMotion.TryParse(body);
|
||||
if (motion is not null)
|
||||
{
|
||||
MotionUpdated?.Invoke(new EntityMotionUpdate(
|
||||
motion.Value.Guid,
|
||||
motion.Value.MotionState));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue