docs: session 2026-04-18 memory + roadmap update

- Adds memory/project_session_2026_04_18.md with full inventory of
  the autonomous AFK session: 14 commits shipping E.1/E.2/E.3/F.1/F.2/
  E.4/E.5/H.1/G.1/G.2 + GameEventWiring glue, 470 → 603 tests.
- Appends both session pages (2026-04-17 bug-bash + 2026-04-18 roadmap
  push) to MEMORY.md.
- Updates docs/plans/2026-04-11-roadmap.md "Phases already shipped"
  table with every phase that landed today.

Current roadmap deltas vs doc-start state:
- Phase D.1 (font/overlay): shipped already, now in table.
- Phase E.1-E.5, F.1-F.2, G.1-G.2, H.1: all shipped today.
- Glue row for GameEventWiring (not a numbered phase but load-bearing).

Deferred items noted in session page:
- Particle GL renderer (E.3b), lighting shader UBO (G.2 second pass),
  PlayerDescription full body parse, dungeon streaming (G.3), char
  create (H.4), allegiance (H.2), quest/dialog VM (H.3).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-18 17:15:32 +02:00
parent 83e8d06ea7
commit 3bea646c62
2 changed files with 191 additions and 0 deletions

View file

@ -0,0 +1,179 @@
# Session 2026-04-18 — Autonomous roadmap push (Phase E + F + H + G)
## Context
User went AFK with direction:
- "Work on the entire roadmap"
- "FULL implementations, NO skeleton implementations"
- "Fall back to decompile retail and holtburger"
- "Implement full animation for monsters AND NPCs AND collision detection"
- "Make proper commits so we can rollback later on"
- "Don't stop! JUST GO"
- Reminder: when connecting to the live ACE server, must log out of
the previous session first; server is always up.
## Delta: 14 commits on main, 470 → 603 tests (+133)
| # | Commit | Phase | Insert | What |
|---|--------|------|--------|------|
| 1 | `4db0b2f` | E.1 | 582 | Motion hook dispatch in AnimationSequencer + PosFrames + vel/omega |
| 2 | `b04d393` | E.1 | 319 | IAnimationHookSink + AnimationHookRouter + GameWindow wiring |
| 3 | `3517239` | E.2 | 1,072 | OpenAL engine + SoundTable cookbook + AudioHookSink |
| 4 | `d3165f9` | E.3 | 820 | ParticleSystem + 13 integrators + ParticleHookSink + registry |
| 5 | `d86fd08` | F.1 | 656 | GameEventEnvelope + GameEventType (94 values) + Dispatcher |
| 6 | `2561f55` | F.2 | 453 | ItemRepository + AppraiseRequest + WieldObject parser |
| 7 | `2e3f9d7` | E.4 | 516 | AttackTargetRequest + 7 combat notifications + CombatState |
| 8 | `c95aedc` | E.5 | 396 | CastSpellRequest (targeted + untargeted) + Spellbook + enchants |
| 9 | `404cab5` | H.1 | 568 | Talk/Tell/ChatChannel outbound + HearSpeech inbound + ChatLog |
| 10 | `6850d71` | G.1 | 566 | DerethDateTime + SkyKeyframe + WorldTimeService |
| 11 | `a28a69a` | G.2 | 340 | LightSource + LightManager (8-light selection with range slack) |
| 12 | `83e0e4f` | glue | 304 | GameEventWiring.WireAll routes dispatcher → state classes |
| 13 | `83e8d06` | wire | 30 | GameWindow exposes Chat/Combat/Spells/Items + WireAll live session |
Total **~6,600 lines of implementation + tests** added today.
## What's functionally alive now
**Every event the server sends now mutates live client state.** Before
today: 0 of 94 GameEvents handled. After today: the priority-0 and
priority-1 events are routed end-to-end (chat, combat, spells,
inventory moves, health updates, system messages, popups).
### Animation & sound (Phase E.1 / E.2 / E.3)
- All 27 `AnimationHookType` values dispatched every frame an entity
crosses an integer frame boundary.
- Forward / Backward / Both direction semantics match ACE exactly.
- `PosFrames` root motion accumulates per-tick for every animation
that carries it.
- `CurrentVelocity` / `CurrentOmega` on the sequencer surface the
active `MotionData`'s kinematics for downstream physics.
- `AnimationHookRouter` fan-outs hooks to multiple sinks; throwing
sink doesn't poison others.
- `OpenAlAudioEngine` with 16-voice 3D pool + retail-faithful
quieter-slot eviction algorithm (matches `FUN_00550ad0` exactly).
Inverse-square distance model, fails open when OpenAL unavailable.
- `SoundCookbook.Roll` picks SoundEntry variants by probability with
silence-tail handling.
- `AudioHookSink` translates Sound / SoundTable / SoundTweaked hooks
into OpenAL calls at the entity's world pos.
- Entity SoundTable auto-registered from `Setup.DefaultSoundTable` at
hydration time — NPCs and monsters get correct creature-specific
footsteps / attack grunts out of the box.
- `ParticleSystem` with 13 integrators (Still, LocalVelocity,
GlobalVelocity, 7 Parabolic variants, Swarm, Explode, Implode),
emit accumulator, overwrite-oldest eviction when pool saturated,
linear fade of size/alpha/color over life.
- `ParticleHookSink` wires CreateParticle / DestroyParticle /
StopParticle / CreateBlockingParticle hooks into the system.
### Network protocol (Phase F.1 / F.2 / E.4 / E.5 / H.1)
- `0xF7B0` envelope parsed (playerGuid + sequence + eventType +
payload slice).
- `GameEventDispatcher` with per-type handlers + unhandled-counts
diagnostic bag + exception isolation per handler.
- 94 `GameEventType` enum values named per ACE conventions.
- Parsers implemented for: ChannelBroadcast, Tell, TransientMessage,
PopupString, WeenieError (+ WithString), UpdateHealth, PingResponse,
MagicUpdateSpell, IdentifyObjectResponse (header only — full
AppraiseInfo deferred), WieldObject, InventoryPutObjInContainer,
VictimNotification, KillerNotification, AttackerNotification,
DefenderNotification, EvasionAttacker/Defender, AttackDone,
MagicUpdateEnchantment, MagicRemoveEnchantment,
MagicDispelEnchantment.
- Outbound actions: AppraiseRequest (0x00C8), AttackTargetRequest
(0x0008), CastSpellRequest untargeted (0x0048) + targeted (0x004A),
ChatRequests.BuildTalk (0x0015), BuildTell (0x005D),
BuildChatChannel (0x0147).
- Standalone GameMessage `HearSpeech` (0x02BB local + 0x02BC ranged)
parser + dispatch.
### Client state (all fed live now)
- `ItemRepository` — add / move / remove / property merge, events
fire to UI on every mutation.
- `CombatState` — per-entity health cache + typed events (damage
taken, dealt, evaded, missed, attack-done).
- `Spellbook` — learned-spell set + active-enchantment layers,
events on add/refresh/remove/purge.
- `ChatLog` — unified ring buffer (500 lines) for every chat source;
adapters for local / ranged / channel / tell / system / popup /
self-echo.
- `WorldTimeService` — server-synced PortalYear clock → DayFraction,
CurrentHour, IsDaytime, CurrentSky (interpolated 4-keyframe),
CurrentSunDirection.
- `LightManager` — 8-light selection, slot 0 = Sun, slots 1..7 =
nearest in-range point/spot, 10% range slack prevents pop.
## Architecture shifts
1. **AcDream.Core.Net → AcDream.Core project reference added.**
GameEventWiring needs both (dispatcher lives in Net, state classes
live in Core). Net now references Core upstream; Core still has
zero Net dependency.
2. **DatReaderWriter 2.1.4 → 2.1.7.** Upgrade was part of Phase E.3
work. 2.1.7 still doesn't expose `ParticleEmitterInfo`, so
EmitterDescRegistry uses synthesized fallback emitters until the
library catches up or we vendor the references/DatReaderWriter
sources.
## Deliberate deferrals (noted, not forgotten)
- **Particle GL renderer (E.3b)**: data layer is complete, integrators
run, hooks route. The billboarded-quad instanced renderer in the
translucent pass is still a todo. Particles are invisible today;
their positions/colors/sizes are correct.
- **PlayerDescription (0x0013)**: dispatcher routes it but we don't
yet deserialize the 10-flag-bitfield property-bundle body. Header
is parsed (for diagnostic).
- **Full AppraiseInfo body**: same story — header parsed, tables not
yet walked. Both the PlayerDescription and AppraiseInfo parsers
share the same packed-HashTable encoding; one parser lands, both
unlock.
- **TurbineChat (0xF7DE)**: nested blob format, not parsed.
- **Phase G.3 dungeons**: portal teleport handling exists; full
dungeon streaming + pink-bubble loading + portal visibility BFS
is the outstanding piece.
- **Phase H.2 Allegiance**: swear/break outbound + tree rendering.
- **Phase H.3 Quest / dialog / emote VM**: 122 EmoteType × 39
Trigger mini-VM deferred.
- **Phase H.4 Character creation**: CharGen dat parser + appearance
picker UI.
## Pickup for next session
The master-synthesis "what unblocks most gameplay fastest" priorities
after today:
1. **Particle GL renderer (E.3b)** — makes all the particle data
actually visible. Portal swirls, chimney smoke, fireplace flames,
spell auras. Can follow WorldBuilder's ParticleBatcher pattern;
billboarded quads in the Phase 9.1 translucent pass.
2. **Dynamic lighting shader (G.2 second commit)** — UBO upload of
`LightManager.Active` + shader fragment loop. Torches would cast
actual light on their surroundings.
3. **AppraiseInfo / PlayerDescription full deserializer** — unlocks
attributes panel, paperdoll, spellbook UI, inventory detail view.
~400 lines of packed-htable code but it's pure data; the UI panels
need it to show anything.
4. **Phase G.3 dungeon streaming** — enter Foundry / any dungeon
portal. Big user-visible win.
5. **Phase H.2 Allegiance** — small, unblocks allegiance chat channel.
6. **Phase H.3/H.4** — quests + char creation, larger.
## Known polish items (parked)
- Walk-backward first-step jitter (small visual bug).
- Walk/run-stop twitch at end of motion (missing SubState→Ready blend).
- Remote-char legs-through-ground Z-offset (server-sent Z vs our
terrain sample at observer XY — needs diagnostic dump).
- Jump feel is ~95% retail-faithful, not 100%.
## Baseline proven
- `dotnet build` green at every commit boundary.
- `dotnet test` green at every commit boundary.
- 470 → 603 tests passed end of session.
- 14 commits all to main; any one can be cherry-picked or reverted
in isolation.