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

8.6 KiB
Raw Blame History

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.