docs: session memory — evening animation investigation + agent dispatch

Captures the diagnosis chain (wrong-first-guess -> parser offset bug
-> handler rewrite -> ACE-confirmed observer-side inference), the
Agent A animation-overhaul merge (10 commits, dead-reckoning + speed
scaling + Commands list + sequence-wide velocity + soft-snap), the
pending Agent B sky/weather/lighting branch, and the orthogonal
wire-layer adds (SocialActions, InventoryActions, AppraiseInfo profile
blobs, 9 extra GameEvent parsers).

Current tree state: 684 tests passing (192 Core.Net + 492 Core),
build green, animation overhaul live on main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-19 10:52:24 +02:00
parent 862cd5662f
commit 7c3ba1e093

View file

@ -12,6 +12,110 @@ User went AFK with direction:
- Reminder: when connecting to the live ACE server, must log out of - Reminder: when connecting to the live ACE server, must log out of
the previous session first; server is always up. the previous session first; server is always up.
## Delta: 30+ commits on main, 470 → 684 tests (+214), continuing
**Status at the time of this update**: continuing the session. The earlier
wire-layer push (E.1-H.2 + AppraiseInfoParser) is stable. The evening
was dominated by a remote-player animation bug investigation + deep-dive
agent dispatch.
## Investigation chain
User reported: "other players don't render properly now. Wrong clothes,
just look like they are lagging forward with run animation. And when
they stop, their running animation is still on."
Iterated on the diagnosis:
1. **First guess (wrong)**: today's AnimationSequencer rewrite caused
it. User tested a d910d57 worktree baseline and confirmed "No its
basically the same" — pre-existing bug, not a regression.
2. **Parser dump revealed**: the UpdateMotion parser had a 2-byte
offset error in its MovementData header skip. ACE's `Align()`
pads based on **absolute stream length** (15 → 16, pad 1 byte,
header total 6 bytes), not relative-to-block (which would pad 3 =
header 8). The old parser assumed 8 → every subsequent field
shifted by 2 → stance + command decoded as the packed-flags dword.
3. **Handler rewrite**: OnLiveMotionUpdated now uses SetCycle directly
instead of GetIdleCycle (which ignored command when stance==0);
preserves current style/motion with "no-change" semantics; full
MotionCommand reconstruction from 16-bit wire values.
4. **ACE source confirmed**: Player_Tick.cs:368 — "the client will
never send a 'client released forward' MoveToState in this
scenario unfortunately. because of this, it's better to have the
'client blip forward' bug without it." → Server never broadcasts
explicit Ready. Observer must infer stopped from position deltas.
Then dispatched two Opus-4.7 parallel agents with high-effort research
+ implementation mandates per user direction ("ultrathink", "super
high effort"):
## Agent A — retail animation overhaul (MERGED to main)
10 commits on worktree-agent-ae8eec87, +32 tests (628→660 before my
orthogonal adds). Shipped:
- **MultiplyCyclicFramerate** on AnimationSequencer — mid-cycle speed
change without restart. Fixes "animation speed doesn't scale with run
rate" for both the local player and remote observers.
- **Dead-reckoning** per remote entity: EMA-smoothed velocity from
consecutive UpdatePosition deltas, per-tick integration using the
sequencer's current velocity rotated by entity orientation, clamp
radius to prevent runaway on lost updates. Fixes "lagging forward"
— remote chars now move smoothly between position updates.
- **Commands[] list parsing** — the InterpretedMotionState tail list
(MotionItem records) was completely unparsed. NPCs transmit waves,
attacks, death throes via this list. Now routed through PlayAction
(for Actions/Modifiers/Emotes) or SetCycle (SubStates).
- **MotionCommandResolver** — reflects the DatReaderWriter.Enums.MotionCommand
enum to reconstruct the full 32-bit command value from the 16-bit
wire field. Prior ad-hoc OR of 0x40000000 sometimes produced
invalid commands.
- **Sequence-wide Velocity/Omega** — was per-node via lookup, broke
during link transitions (cycle's velocity wasn't surfaced while a
link played). Now matches ACE Sequence.Velocity (last-added-wins,
retained across link/cycle boundary).
- **Omega integration to entity rotation** — TurnRight/TurnLeft cycles
now smoothly rotate the entity each tick between server updates.
- **Soft-snap residual** — server UpdatePosition is authoritative but
blended over ~300ms so corrections don't look like teleports.
- **Stop detection hardening** — 300ms position-stale + velocity-dead
double signal; dedup on respawn clears stale dead-reckon state.
### Deferred by Agent A
- PosFrames root motion drain (most AC locomotion uses MotionData.Velocity)
- Full MotionState struct port (Modifier list, Action queue, substateMod)
- AttackHook → combat damage frame sink
- ReplaceObjectHook → weapon draw mesh swap
- Stance transition double-link chain (HandCombat → SwordCombat multi-link)
## Agent B — sky / weather / lighting (in progress)
Still running. When it completes, will ship:
- SkyRenderer with retail GfxObj-based sky objects (not a textured sphere)
- WeatherRenderer (rain/snow/fog via existing ParticleSystem)
- Dynamic-lighting shader UBO (8-light UBO per R13 §12.3)
- Torch/fireplace/spell-aura LightSource registration via SetLightHook
## Additional orthogonal work this session (merged on main)
- **UpdateMotion parser fix** — 6-byte header (not 8). Committed
before agent dispatch.
- **GameWindow stop detection** — 400ms position-stale → Ready (later
superseded by Agent A's 300ms + velocity-dead version).
- **AppraiseInfoParser profile blobs** — ArmorProfile / CreatureProfile
/ WeaponProfile / ArmorLevels / enchantment bitfields. +6 tests.
- **SocialActions** — QueryHealth (0x01BF), PingRequest (0x01E9),
FellowshipCreate/Quit/Dismiss/Recruit/Update, SetCharacterOptions,
AddChannel/RemoveChannel. +10 tests.
- **InventoryActions** — StackableMerge/Split×3, GiveObjectRequest,
AddShortcut, RemoveShortcut, TeleToPoi. +8 tests.
- **9 more GameEvent parsers** — UseDone, PutObjectIn3D,
InventoryServerSaveFailed, CloseGroundContainer, TradeFailure,
AddToTrade, AcceptTrade, QueryItemManaResponse,
CharacterConfirmationRequest.
## Delta: 19 commits on main, 470 → 628 tests (+158) ## Delta: 19 commits on main, 470 → 628 tests (+158)
| # | Commit | Phase | Insert | What | | # | Commit | Phase | Insert | What |