acdream/tests/AcDream.App.Tests
Erik d32ef388f0 feat(chat): CT-A5 — clicking a speaker's name opens a tell
Campaign CT slice A5, closing Group A. Retail's
gmMainChatUI::RecvNotice_TextTag_IIDStringClick @0x004CCE10 ->
ChatInterface::StartTell @0x004F41F0 writes "@tell {Name}, " into the chat
entry and takes keyboard focus; clicking a green name here now does the same.

The trailing space is deliberate — without it the first character the player
types joins the comma.

Three seams, each narrow on purpose:

  - UiText.OnCharClick is offered the character under a left click before the
    element-wide OnClick, and consuming it suppresses that. Kept separate
    because a tag click is POSITIONAL and an element click is not; folding
    them together would make every text element with an OnClick swallow tag
    clicks.
  - TaggedRangesForFragment returns tagged column ranges relative to the
    FRAGMENT, because that is what a click resolves to — UiText.HitChar gives
    a line index into the WRAPPED list plus a column within it. Line-relative
    ranges would land every click on a wrapped line at the wrong characters.
  - The controller caches those ranges alongside the runs it already caches,
    so the per-click lookup reads the same cache the draw does.

The hit test is half-open: a caret slot sits BETWEEN glyphs, so clicking just
past a name's last letter belongs to the space after it, not the name. Pinned
by theory rather than left to chance, since off-by-one here means clicking a
name sometimes does nothing.

StartTell uses the tag's NAME, not its object id — retail carries the id but
this handler never reads it, so the tell still addresses correctly for someone
who has since moved out of range.

Group A is complete: names are green (A4) and clickable (A5). Ready for the
user's visual gate.

Solution builds clean; full hermetic gate green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 07:34:58 +02:00
..
Architecture test: replace gameplay owner source freezes 2026-08-18 16:49:38 +02:00
Audio feat(audio): Campaign A slice A2 — retail's 2D pan+gain mixer replaces AL 3D 2026-08-08 21:58:50 +02:00
Combat fix(ui,runtime): OP4 review fixes — live re-seed, enable-gating, Combat panel re-point, universal timestamps 2026-08-11 05:30:26 +02:00
Composition fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Configuration fix(app): Campaign LA gate round 2 — session-config launches force the retail UI on 2026-08-15 08:42:33 +02:00
Credentials test: make prerequisite lanes fail honestly 2026-08-18 12:09:41 +02:00
Diagnostics test: replace campaign labels with behavior names 2026-08-18 12:25:00 +02:00
Input test: replace input and physics source freezes 2026-08-18 15:31:57 +02:00
Interaction fix: social panel completion batch (user gate 2026-08-13, "fix all") 2026-08-13 19:30:51 +02:00
Net fix(chat): announce enchantment expiry; stop double-printing tells 2026-08-21 06:11:33 +02:00
Physics test: replace input and physics source freezes 2026-08-18 15:31:57 +02:00
Platform feat(platform): Campaign LA LA0 — extract ApplicationPathSet to AcDream.Platform 2026-08-14 15:19:02 +02:00
Plugins feat(plugins): MossTank — a self-buffing plugin, and the automation surface it needed 2026-08-20 16:22:28 +02:00
Rendering fix(world): rotate the DAT-scenery root too — the flyers actually orbit now 2026-08-21 05:52:44 +02:00
Runtime test: replace gameplay owner source freezes 2026-08-18 16:49:38 +02:00
Settings fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Spells feat(headless): share immutable gameplay content 2026-07-27 09:00:48 +02:00
Streaming test: replace streaming source freezes 2026-08-18 15:14:41 +02:00
UI feat(chat): CT-A5 — clicking a speaker's name opens a tell 2026-08-21 07:34:58 +02:00
World test: replace create authority source pin 2026-08-18 16:52:22 +02:00
AcDream.App.Tests.csproj build: make release restore reproducible 2026-08-18 10:29:00 +02:00
BoundedTestDatCollection.cs perf(content): remove exception-driven setup probes 2026-07-24 15:12:21 +02:00
FramePhaseTestDoubles.cs refactor(runtime): move session lifetime and ordered transport 2026-07-25 19:39:24 +02:00
FrameProfilerReportTests.cs perf(diag): complete trustworthy Slice A capture tooling 2026-07-24 12:46:51 +02:00
FrameStatsBufferTests.cs fix(pipeline): MP0 - profiler toggle-path hygiene + Max() seed (review follow-up) 2026-07-05 19:26:28 +02:00
GameRuntimeTestFactory.cs refactor(runtime): cut graphical host over to canonical root 2026-07-26 19:06:09 +02:00
GlobalUsings.cs feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
LiveEntityRuntimeFixture.cs test(runtime): restore the world-frame precondition across first-entry fixtures 2026-08-03 13:32:28 +02:00
LiveEntitySpawnFixture.cs feat(runtime): C3c - production placement cutover: both hosts on the residence conductors (routes 1+8) 2026-08-02 18:10:33 +02:00
packages.neutral.lock.json build: make release restore reproducible 2026-08-18 10:29:00 +02:00
RuntimeDatAccessArchitectureTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeDatCollectionFactoryTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeOptionsRetailUiTests.cs test(runtime): add deterministic world gate artifacts 2026-07-20 22:37:16 +02:00
RuntimeOptionsTests.cs fix(launcher): close Campaign LA LA1 review findings 2026-08-14 17:00:09 +02:00
RuntimeWorldTransitTestDriver.cs refactor(runtime): own teleport destination correlation 2026-07-26 17:52:34 +02:00
ZeroAllocationProbe.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00
ZeroAllocationProbeTests.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00