acdream/memory/project_session_2026_04_18.md
Erik 3bea646c62 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>
2026-04-18 17:15:32 +02:00

179 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.