docs(phys L.2g): slice 1 shipped handoff + B.4 gap discovery + plan-of-record
L.2g slice 1 is CODE-COMPLETE: parser + registry mutator + WorldSession dispatcher + GameWindow subscriber (4 commits:2459f28,d538915,536a608,108e386). Build clean, 6 new tests pass, baseline-stable across the full suite. Per-commit + final integration code reviews all approved. Visual verification deferred: while running the Holtburg-doorway test, Phase B.4's outbound Use handler turned out to be unwired. The wire builders (InteractRequests.BuildUse), classes (SelectionState, WorldPicker), input-action enums, and keybindings all exist — but GameWindow.OnInputAction has no case for SelectDblLeft, so the click silently does nothing. The inbound L.2g chain we just landed can't fire until something sends an outbound Use. This commit captures the handoff + reframes next-session work: * docs/research/2026-05-12-l2g-slice1-shipped-handoff.md (NEW) Full evidence: 4 shipped commits, end-to-end code flow, B.4 discovery explanation, 4 minor + 1 Important review notes (the Important one is a test-coverage gap that the B.4b visual test will settle automatically), reproducibility recipe, next-session pick. * CLAUDE.md "Currently in Phase L.2" paragraph: L.2g slice 1 code shipped; visual test deferred to B.4b. Next-phase-candidates list: L.2g slice 1 (now done) replaced with the B.4b candidate pointing at the slice scope. * docs/plans/2026-04-29-movement-collision-conformance.md L.2g section gains a "Current shipped slice (2026-05-12):" table listing the 4 commits. * docs/plans/2026-05-12-milestones.md M1 phase-list updated: L.2g slice 1 (code) shipped; B.4 renamed "B.4 / B.4b" with the gap-discovery note + B.4b shape. * docs/ISSUES.md New issue #57 (HIGH) for the B.4 interaction-handler gap. Promoted to Phase B.4b; will close as DONE (promoted to Phase B.4b) when B.4b's design spec lands. * Memory file project_interaction_pipeline.md (in personal memory dir, not in this commit) updated to reflect reality. Next session: Phase B.4b (~30-50 LOC, 1-2 subagent dispatches, ~30 min). Subscribe SelectDblLeft -> WorldPicker.Pick -> InteractRequests.BuildUse -> _liveSession.SendGameMessage. Same Holtburg-doorway visual test verifies both L.2g slice 1 and B.4b in one pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
108e3868a5
commit
aba6c9ac7f
5 changed files with 369 additions and 27 deletions
58
CLAUDE.md
58
CLAUDE.md
|
|
@ -618,16 +618,27 @@ acdream's plan lives in two files committed to the repo:
|
|||
approval.
|
||||
|
||||
**Currently in Phase L.2 (Movement & Collision Conformance).** L.2a slices
|
||||
1+2+3 + L.2d slice 1+1.5 shipped 2026-05-12. L.2d closed at the Holtburg
|
||||
site ("watch-and-wait" — no more slices until a new shape-fidelity bug
|
||||
shows up elsewhere); doorway blocker identified as a Door entity, not
|
||||
building BSP. L.2g (dynamic PhysicsState toggling — doors) brainstormed
|
||||
and design-spec'd 2026-05-12 evening; **the natural next step is the
|
||||
L.2g slice 1 implementation** (parse `SetState` 0xF74B, plumb new
|
||||
PhysicsState into ShadowObjectRegistry, verify Holtburg inn doorway).
|
||||
1+2+3 + L.2d slice 1+1.5 + L.2g slice 1 shipped 2026-05-12. L.2g slice 1
|
||||
is CODE-COMPLETE (parser + registry mutator + WorldSession dispatcher +
|
||||
GameWindow subscriber, 4 commits, build green, 6 new tests pass), but
|
||||
its visual verification is **deferred to the B.4b session** — clicking
|
||||
on a door does nothing today because Phase B.4's input-action handler
|
||||
was never wired (the wire builders and bindings exist, but
|
||||
`GameWindow.OnInputAction` has no case for `SelectDblLeft`, so the
|
||||
outbound Use never sends). **The natural next step is Phase B.4b —
|
||||
finish the outbound Use handler wiring** (subscribe `SelectDblLeft` →
|
||||
`WorldPicker.Pick` → `InteractRequests.BuildUse` → send), then re-run
|
||||
the Holtburg inn-doorway visual test which verifies both L.2g slice 1
|
||||
and B.4b in one pass. Estimated 30-50 LOC, ~30 min, 1-2 subagent
|
||||
dispatches.
|
||||
|
||||
L.2g slice 1 ship handoff: [`docs/research/2026-05-12-l2g-slice1-shipped-handoff.md`](docs/research/2026-05-12-l2g-slice1-shipped-handoff.md)
|
||||
— full evidence + the 4 minor review notes + the 1 Important test-coverage
|
||||
gap for `ShouldSkip` (the B.4b visual test's hex-dump will settle whether
|
||||
ACE sends `state=0x4` alone or `0x14`).
|
||||
Design spec: [`docs/superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md`](docs/superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md).
|
||||
Implementation plan: [`docs/superpowers/plans/2026-05-12-phase-l2g-slice1.md`](docs/superpowers/plans/2026-05-12-phase-l2g-slice1.md).
|
||||
L.2d ship handoff: [`docs/research/2026-05-13-l2d-slice1-shipped-handoff.md`](docs/research/2026-05-13-l2d-slice1-shipped-handoff.md).
|
||||
L.2a→L.2d handoff (now superseded by the L.2d ship): [`docs/research/2026-05-12-l2a-shipped-l2d-handoff.md`](docs/research/2026-05-12-l2a-shipped-l2d-handoff.md).
|
||||
|
||||
**Phase L.2a (Truth & Diagnostics) slices 1-3 shipped 2026-05-12.**
|
||||
Three commits land the L.2 "make every bad movement outcome explainable"
|
||||
|
|
@ -705,18 +716,25 @@ together comprise the streaming + rendering perf foundation for the
|
|||
project.
|
||||
|
||||
**Next phase candidates (in rough preference order):**
|
||||
- **L.2g slice 1 implementation — dynamic PhysicsState toggling for doors.**
|
||||
Direct continuation of tonight's L.2d slice 1.5 evidence: parse inbound
|
||||
`SetState (0xF74B)` wire message, plumb the new `PhysicsState` value into
|
||||
`ShadowObjectRegistry`'s cached entity state so the existing
|
||||
`CollisionExemption.IsExempt(...)` check sees up-to-date bits, and verify
|
||||
the Holtburg inn-door scenario walks through cleanly when the server flips
|
||||
Ethereal. Unblocks the M1 demo's *"open the inn door"* line. Spec:
|
||||
[`docs/superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md`](docs/superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md).
|
||||
**Note:** triage the 8 pre-existing test failures still hanging over the
|
||||
physics modules first (none introduced by L.2a/L.2d slices — verified by
|
||||
stash + rerun — but most touch code adjacent to where L.2g will plumb the
|
||||
new state mutator).
|
||||
- **Phase B.4b — finish the outbound Use handler wiring.**
|
||||
Direct M1 blocker discovered while running the L.2g slice 1 visual
|
||||
test: the wire builders (`InteractRequests.BuildUse`), classes
|
||||
(`SelectionState`, `WorldPicker`), input-action enum entries
|
||||
(`SelectDblLeft` etc.), and keybindings (LMB-dblclick → `SelectDblLeft`)
|
||||
all ship today, but `GameWindow.OnInputAction`'s switch has NO case
|
||||
for any of the `Select*` actions — clicking on a door fires the
|
||||
diagnostic `[input] SelectDblLeft Press` but nothing downstream
|
||||
listens. Memory file `project_interaction_pipeline.md` updated to
|
||||
reflect this reality. Shape: subscribe `InputAction.SelectDblLeft`
|
||||
→ build a world ray from current mouse → `WorldPicker.Pick(...)` →
|
||||
store in `_selection` → call `InteractRequests.BuildUse(seq, guid)`
|
||||
+ `_liveSession.SendGameMessage(body)`. Probably also subscribe
|
||||
`SelectLeft` for select-without-use and `UseSelected` for the R
|
||||
hotkey. Estimate: 30-50 LOC, 1-2 subagent dispatches, ~30 min.
|
||||
Verifies L.2g slice 1 in the same Holtburg-doorway visual test once
|
||||
it lands. Full context:
|
||||
[`docs/research/2026-05-12-l2g-slice1-shipped-handoff.md`](docs/research/2026-05-12-l2g-slice1-shipped-handoff.md)
|
||||
"Why the visual test is deferred" section.
|
||||
- **Triage the chronic open-issue list** in `docs/ISSUES.md` — #2 (lightning),
|
||||
#4 (sky horizon-glow), #28 (aurora), #29 (cloud thinness), #37 (humanoid
|
||||
coat), #50 (stray tree), #41 (remote-motion blips) have been open since
|
||||
|
|
|
|||
|
|
@ -46,6 +46,65 @@ Copy this block when adding a new issue:
|
|||
|
||||
# Active issues
|
||||
|
||||
## #57 — B.4 interaction-handler missing: clicking on doors / NPCs / items silently does nothing
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** HIGH (M1 blocker — demo target *"open the inn door, click an NPC, pick up an item"* is fully blocked)
|
||||
**Filed:** 2026-05-12
|
||||
**Component:** input / interaction / `GameWindow.OnInputAction`
|
||||
|
||||
**Description:** Discovered 2026-05-12 while running the L.2g slice 1
|
||||
visual test. Phase B.4 (2026-04-28) shipped half of itself: the wire-
|
||||
message builders (`InteractRequests.BuildUse` / `BuildUseWithTarget` /
|
||||
`BuildPickUp`), the supporting classes (`SelectionState`, `WorldPicker`),
|
||||
the `InputAction` enum entries (`SelectLeft`, `SelectDblLeft`,
|
||||
`SelectRight`, `SelectDblRight`, `UseSelected`, `SelectionPickUp`, etc.),
|
||||
and the default keybindings (LMB → `SelectLeft`, LMB-dblclick →
|
||||
`SelectDblLeft`, RMB → `SelectRight`, R → `UseSelected`, F →
|
||||
`SelectionPickUp`). What was never shipped: a case for ANY of those
|
||||
actions in `GameWindow.OnInputAction`'s switch. The runtime diagnostic
|
||||
`[input] SelectLeft Press` fires when you click — confirming the
|
||||
dispatcher resolves the chord — but nothing downstream listens, so the
|
||||
click silently does nothing. Neither does double-click, R, or F. The
|
||||
inbound side (`MoveToObjectReceived`, `StateUpdated` after L.2g slice 1)
|
||||
is wired and ready; the block is purely outbound.
|
||||
|
||||
**Root cause / status:** B.4 handler integration step was evidently
|
||||
dropped or never landed. Memory file
|
||||
`memory/project_interaction_pipeline.md` was updated 2026-05-12 to
|
||||
reflect this reality (previous text claimed shipped).
|
||||
|
||||
**Files:**
|
||||
- `src/AcDream.App/Rendering/GameWindow.cs` — `OnInputAction` switch
|
||||
around line 8546+ has no `Select*` cases.
|
||||
- `src/AcDream.Core.Net/Messages/InteractRequests.cs` — wire builders
|
||||
exist but have zero callers in `src/`.
|
||||
- `src/AcDream.Core/Selection/SelectionState.cs` — class exists, zero
|
||||
production callers.
|
||||
- `src/AcDream.App/Rendering/WorldPicker.cs` — class exists, zero
|
||||
production callers.
|
||||
- `src/AcDream.UI.Abstractions/Input/KeyBindings.cs:300-320` — bindings
|
||||
for `SelectLeft` / `SelectDblLeft` / `SelectRight` / `SelectDblMid`
|
||||
exist.
|
||||
|
||||
**Research:** [docs/research/2026-05-12-l2g-slice1-shipped-handoff.md](research/2026-05-12-l2g-slice1-shipped-handoff.md)
|
||||
"Why the visual test is deferred" section has the full investigation.
|
||||
|
||||
**Acceptance:** Double-left-clicking on a door in the Holtburg inn
|
||||
doorway sends a `0xF7B1 / 0x0036 Use` to the server, the server flips
|
||||
the door's `Ethereal` bit and broadcasts `SetState (0xF74B)`, the
|
||||
L.2g-slice-1 chain mutates `ShadowObjectRegistry`, the
|
||||
`CollisionExemption.ShouldSkip` check honors it, and the player can
|
||||
walk through the doorway. Visual verification + log grep (per the
|
||||
L.2g handoff's reproducibility recipe) both pass.
|
||||
|
||||
**Status promotion:** This is a phase-sized follow-up (estimated
|
||||
30-50 LOC, ~30 min). Promoted to **Phase B.4b** in the L.2 milestone
|
||||
context and the CLAUDE.md "Next phase candidates" list. Will be closed
|
||||
as `DONE (promoted to Phase B.4b)` once that phase's design spec lands.
|
||||
|
||||
---
|
||||
|
||||
## #55 — Static-entity slow path reports ~1.45M `meshMissing` per 5s at r4 standstill
|
||||
|
||||
**Status:** OPEN
|
||||
|
|
|
|||
|
|
@ -266,6 +266,24 @@ Full design spec:
|
|||
M1 critical path: this slice unblocks the *"open the inn door"* demo
|
||||
scenario.
|
||||
|
||||
Current shipped slice (2026-05-12):
|
||||
|
||||
| Commit | Subject |
|
||||
|---|---|
|
||||
| `2459f28` | `feat(phys L.2g slice 1): inbound SetState (0xF74B) parser` |
|
||||
| `d538915` | `feat(phys L.2g slice 1): ShadowObjectRegistry.UpdatePhysicsState` |
|
||||
| `536a608` | `feat(phys L.2g slice 1): WorldSession dispatches SetState (0xF74B) + hex probe` |
|
||||
| `108e386` | `feat(phys L.2g slice 1): GameWindow routes SetState + extends [entity-source] log` |
|
||||
|
||||
Slice 1 is CODE-COMPLETE: parser + registry mutator + WorldSession
|
||||
dispatcher + GameWindow subscriber. 6 new tests pass (3 parser + 3
|
||||
registry). Build clean. Per-commit + final integration code reviews
|
||||
all approved. **Visual verification deferred to Phase B.4b** — the
|
||||
inbound SetState chain can't fire at runtime until B.4b finishes the
|
||||
outbound Use handler. See
|
||||
[docs/research/2026-05-12-l2g-slice1-shipped-handoff.md](../research/2026-05-12-l2g-slice1-shipped-handoff.md)
|
||||
for full evidence + the 4 minor + 1 Important review notes.
|
||||
|
||||
## Named Retail Anchors
|
||||
|
||||
Primary source: `docs/research/named-retail/acclient_2013_pseudo_c.txt`.
|
||||
|
|
|
|||
|
|
@ -101,13 +101,19 @@ doorway. Open the inn door. Click an NPC and see selection feedback. Pick
|
|||
up an item from the ground.
|
||||
|
||||
**Phases to ship:**
|
||||
- **L.2 (all sub-lanes a–g)** — Movement & Collision Conformance. Currently
|
||||
active; L.2a slices 1+2+3 + L.2d slice 1+1.5 shipped 2026-05-12. L.2g
|
||||
(dynamic PhysicsState toggling — doors) brainstormed + design-spec'd
|
||||
2026-05-12 evening, implementation next.
|
||||
- **B.4** — `Use` / `UseWithTarget` / `PickUp` outbound messages
|
||||
(shipped 2026-04-28; remains in M1 scope until L.2g completes the
|
||||
inbound-state half of the Use round-trip).
|
||||
- **L.2 (all sub-lanes a–g)** — Movement & Collision Conformance.
|
||||
L.2a slices 1+2+3 + L.2d slice 1+1.5 + L.2g slice 1 (code) shipped
|
||||
2026-05-12. L.2g slice 1 visual verification deferred to B.4b session
|
||||
(the inbound SetState chain can't fire until the outbound Use sends).
|
||||
- **B.4 / B.4b** — `Use` / `UseWithTarget` / `PickUp` interaction.
|
||||
B.4 (2026-04-28) shipped the wire builders, `SelectionState`,
|
||||
`WorldPicker`, the input-action enums, and the keybindings — but
|
||||
*not* the `GameWindow.OnInputAction` handler that ties them
|
||||
together. As of 2026-05-12, clicking on a door silently does nothing.
|
||||
**B.4b** is the small follow-up slice (~30-50 LOC) that subscribes
|
||||
`SelectDblLeft` and routes through pick → BuildUse → send. Once B.4b
|
||||
lands, the same Holtburg-doorway visual test verifies both L.2g
|
||||
slice 1 and B.4b in one pass.
|
||||
|
||||
**Freeze on landing:**
|
||||
- L.2 zone (collision, cell ownership, transition parity, wire authority)
|
||||
|
|
|
|||
241
docs/research/2026-05-12-l2g-slice1-shipped-handoff.md
Normal file
241
docs/research/2026-05-12-l2g-slice1-shipped-handoff.md
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
# L.2g slice 1 shipped — handoff (code-complete; visual test deferred)
|
||||
|
||||
**Date:** 2026-05-12 evening.
|
||||
**Branch:** `claude/gallant-mestorf-3bf2e3` (ready to merge to main).
|
||||
**Predecessors:**
|
||||
- [2026-05-13-l2d-slice1-shipped-handoff.md](2026-05-13-l2d-slice1-shipped-handoff.md) — the L.2d trace that identified Door entities as the Holtburg doorway blocker, motivating L.2g.
|
||||
- [docs/superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md](../superpowers/specs/2026-05-12-l2g-dynamic-physicsstate-design.md) — the L.2g design spec (commit `2c10dd4`).
|
||||
- [docs/superpowers/plans/2026-05-12-phase-l2g-slice1.md](../superpowers/plans/2026-05-12-phase-l2g-slice1.md) — the L.2g slice 1 implementation plan (commit `869677b`).
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
|
||||
L.2g slice 1 **code is complete and unit-tested.** The four commits land
|
||||
the full inbound `SetState (0xF74B)` pipeline: parser → WorldSession
|
||||
event → GameWindow handler → `ShadowObjectRegistry.UpdatePhysicsState`.
|
||||
After this slice, the existing `CollisionExemption.ShouldSkip`
|
||||
short-circuit (cited at `acclient_2013_pseudo_c.txt:276782`) honors
|
||||
runtime ETHEREAL flips without any resolver-path edit.
|
||||
|
||||
**The visual verification at Holtburg's inn doorway is deferred to the
|
||||
next session.** Cause: Phase B.4's outbound Use handler turns out to be
|
||||
unwired — clicking on a door silently does nothing because no
|
||||
production code subscribes to the `SelectLeft` / `SelectDblLeft` input
|
||||
actions. Without the outbound Use, the server never sees a "open the
|
||||
door" request, so the inbound SetState we just ported never fires.
|
||||
|
||||
L.2g slice 1 is the inbound half of the round-trip. Phase **B.4b** (a
|
||||
small ~30-50 LOC slice) is the outbound half. Both halves are required
|
||||
for the M1 demo target *"open the inn door."* B.4b is the next session's
|
||||
work.
|
||||
|
||||
---
|
||||
|
||||
## What shipped on this branch
|
||||
|
||||
| Commit | Subject |
|
||||
|---|---|
|
||||
| [`2459f28`](.) | `feat(phys L.2g slice 1): inbound SetState (0xF74B) parser` |
|
||||
| [`d538915`](.) | `feat(phys L.2g slice 1): ShadowObjectRegistry.UpdatePhysicsState` |
|
||||
| [`536a608`](.) | `feat(phys L.2g slice 1): WorldSession dispatches SetState (0xF74B) + hex probe` |
|
||||
| [`108e386`](.) | `feat(phys L.2g slice 1): GameWindow routes SetState + extends [entity-source] log` |
|
||||
|
||||
Plus docs/scaffolding earlier in the session:
|
||||
- `2c10dd4` — L.2g design spec + L.2 plan-of-record + milestones + CLAUDE.md updates.
|
||||
- `869677b` — L.2g slice 1 implementation plan (this doc's companion).
|
||||
|
||||
**Build:** clean. **Tests:** 6 new tests pass (3 for parser, 3 for
|
||||
registry mutator). Full suite: 1037 pass / 8 pre-existing-baseline fail.
|
||||
No regressions. Per-commit + final integration code reviews all approved.
|
||||
|
||||
---
|
||||
|
||||
## What the code now does end-to-end
|
||||
|
||||
When the server broadcasts a `SetState (0xF74B)`:
|
||||
|
||||
1. **Parse** — `WorldSession`'s dispatcher routes opcode `0xF74B` into
|
||||
`SetState.TryParse(body)`, which returns
|
||||
`SetState.Parsed(Guid, PhysicsState, InstanceSequence, StateSequence)`.
|
||||
2. **Probe** (gated on `ACDREAM_PROBE_BUILDING=1`) — one-shot per
|
||||
session, dumps the first message's body bytes as
|
||||
`[setstate-hex] body.len=N first-N-bytes: 4B F7 ...` for wire-format
|
||||
confidence.
|
||||
3. **Event** — `WorldSession.StateUpdated` fires with the parsed value.
|
||||
4. **Subscribe** — `GameWindow.OnLiveStateUpdated` (added to the live-
|
||||
session attach block alongside `OnLiveVectorUpdated`) calls
|
||||
`_physicsEngine.ShadowObjects.UpdatePhysicsState(parsed.Guid, parsed.PhysicsState)`.
|
||||
5. **Mutate** — `ShadowObjectRegistry.UpdatePhysicsState` walks every
|
||||
per-cell list the entity occupies and rewrites `list[i] with { State = newState }`.
|
||||
6. **Per-tick diagnostic** (same probe flag) — emits
|
||||
`[setstate] guid=0x... state=0x... instSeq=... stateSeq=...` for the
|
||||
greppable trail.
|
||||
7. **Resolver** — next physics tick, `FindObjCollisions` calls
|
||||
`CollisionExemption.ShouldSkip(entry.State, entry.Flags, moverState)`
|
||||
on the entity. The check is unchanged from L.2d slice 1; it
|
||||
short-circuits when `(state & ETHEREAL_PS) != 0 && (state & IGNORE_COLLISIONS_PS) != 0`.
|
||||
|
||||
**Slice 0.5 freebie folded in:** all 6 `[entity-source]` probe-log
|
||||
sites in `GameWindow.cs` now emit `state=0x{state:X8} flags={flags}`
|
||||
so ETHEREAL flips are greppable end-to-end from spawn through state
|
||||
change.
|
||||
|
||||
---
|
||||
|
||||
## Why the visual test is deferred — the B.4 discovery
|
||||
|
||||
Before launching the visual test, the user reported that right-click
|
||||
in-client was bound to camera orbit (correctly), and asked whether
|
||||
left-click should open a door. Investigation produced this finding:
|
||||
|
||||
| Component | State |
|
||||
|---|---|
|
||||
| `InteractRequests.BuildUse(seq, guid)` wire builder | ✅ implemented + tested |
|
||||
| `SelectionState`, `WorldPicker` classes | ✅ exist in source |
|
||||
| `InputAction.SelectLeft` / `SelectDblLeft` / `SelectRight` enum | ✅ defined |
|
||||
| KeyBindings: LMB → `SelectLeft`, LMB-dblclick → `SelectDblLeft`, RMB → `SelectRight` | ✅ wired in `KeyBindings.cs:300-320` |
|
||||
| `GameWindow.OnInputAction` switch case for `Select*` | ❌ **missing** |
|
||||
| Any production caller of `SelectionState`, `WorldPicker`, `InteractRequests.BuildUse` | ❌ **none in `src/`** |
|
||||
|
||||
The diagnostic line `[input] SelectLeft Press` fires on LMB-click — the
|
||||
dispatcher knows the action — but nothing downstream listens. The
|
||||
click silently does nothing. The R hotkey similarly does nothing
|
||||
because the corresponding `UseSelected` case is also absent from the
|
||||
switch.
|
||||
|
||||
So the M1 outbound Use path is **half-shipped**: every component below
|
||||
the handler exists, but the handler that ties them together was never
|
||||
landed (despite a 2026-04-28 memory entry claiming "B.4 shipped").
|
||||
Phase B.4b is the slice that fixes this.
|
||||
|
||||
This is **not** an L.2g defect. L.2g's code path is correct and unit-
|
||||
tested; it just can't be exercised at runtime until the outbound Use
|
||||
sends a SetState-triggering request to the server.
|
||||
|
||||
---
|
||||
|
||||
## Open notes from reviews (minor — defer to next polish pass)
|
||||
|
||||
The per-commit and final integration code reviews approved every commit.
|
||||
Four observations flagged as Minor that are worth folding into a future
|
||||
polish pass:
|
||||
|
||||
1. **`SetState.cs` "total body size" phrasing diverges from `VectorUpdate.cs`.**
|
||||
New form: `"Total body size: 16 bytes (4-byte opcode + 12-byte payload)"`.
|
||||
Sibling form: `"Total body size after opcode: 32 bytes"`. The new form
|
||||
is more self-documenting, but the spec asked to align with the
|
||||
sibling. Cosmetic.
|
||||
2. **`[setstate-hex]` log uses redundant `Math.Min(body.Length, 32)`.**
|
||||
Called twice in the same line; could be hoisted to a local.
|
||||
Harmless for a one-shot diagnostic.
|
||||
3. **`WorldSession.cs` uses the fully-qualified
|
||||
`AcDream.Core.Physics.PhysicsDiagnostics.ProbeBuildingEnabled`** instead
|
||||
of adding `using AcDream.Core.Physics;` and using the short form.
|
||||
Every other call site in `GameWindow.cs` and `BSPQuery.cs` uses the
|
||||
unqualified form. Style inconsistency.
|
||||
4. **`[setstate]` diagnostic emits guid + state as hex but instSeq +
|
||||
stateSeq as decimal.** Cosmetic.
|
||||
|
||||
### One Important review note (worth following up explicitly)
|
||||
|
||||
The final integration reviewer flagged: the test
|
||||
`UpdatePhysicsState_FlipsEthereal_NextLookupSeesNewBits` asserts the
|
||||
cached state changes to `0x4` but does **not** verify the chain
|
||||
through `CollisionExemption.ShouldSkip`. That short-circuit requires
|
||||
**both** `ETHEREAL_PS (0x4)` AND `IGNORE_COLLISIONS_PS (0x10)` to be
|
||||
set simultaneously (`(state & 0x4) && (state & 0x10)`). A state of
|
||||
`0x4` alone does NOT exempt collision. Per the reviewer, ACE's
|
||||
`PhysicsObj.cs:787-791` may set both bits when doors open (broadcast
|
||||
value `0x14` or higher) — but this is not verified by the test suite.
|
||||
|
||||
**The B.4b visual test will settle this definitively:** the slice-1
|
||||
hex-dump probe will capture the real `state=0x????????` wire value the
|
||||
first time a door opens. If ACE sends `0x14` or higher, the existing
|
||||
chain works as-is. If ACE sends `0x4` only, we need a tiny adjustment
|
||||
to `CollisionExemption.cs` (the `&&` would become `||`, OR we make the
|
||||
collision exemption fire on ETHEREAL alone, OR we widen the test).
|
||||
|
||||
**Action for B.4b session:** after the door-open visual test, grep the
|
||||
launch log for `[setstate-hex]` and the `[setstate]` line that fires on
|
||||
the Use → confirm the state bits ACE actually sends. If `0x4` only,
|
||||
file a tiny L.2g slice 1b to widen `CollisionExemption.ShouldSkip` or
|
||||
the test's assertion.
|
||||
|
||||
---
|
||||
|
||||
## Next session
|
||||
|
||||
**Pick: Phase B.4b — finish the outbound Use handler wiring.**
|
||||
|
||||
Concretely:
|
||||
- Subscribe `InputAction.SelectDblLeft` in `GameWindow.OnInputAction`
|
||||
switch.
|
||||
- Build a world ray from current mouse position
|
||||
(`WorldPicker.BuildRay(mouse, vp, view, proj)`).
|
||||
- Pick the closest entity (`WorldPicker.Pick(ray, entities, cache, skipGuid, maxDist)`).
|
||||
- Store result in `_selection` (`SelectionState.Set(guid)`).
|
||||
- Call `InteractRequests.BuildUse(seq, guid)` + `_liveSession.SendGameMessage(body)`.
|
||||
- Probably also subscribe `InputAction.SelectLeft` for select-without-
|
||||
use (single-click selects; double-click selects + uses).
|
||||
- Optionally subscribe `InputAction.UseSelected` (R hotkey) to send Use
|
||||
on the already-selected guid.
|
||||
- Sequence-number management — there's a game-action sequence counter
|
||||
on `WorldSession` already used by the outbound chat path; reuse it.
|
||||
|
||||
Estimate: 30-50 LOC, 1-2 subagent-driven implementations + reviews, ~30 min.
|
||||
|
||||
Once B.4b lands, **immediately re-run the Holtburg inn doorway visual
|
||||
test** with `ACDREAM_PROBE_BUILDING=1`. Both L.2g slice 1 + B.4b are
|
||||
verified by the same scenario; no separate L.2g visual test needed.
|
||||
|
||||
---
|
||||
|
||||
## Reproducibility
|
||||
|
||||
Same launch recipe as L.2d slice 1 (see CLAUDE.md "Running the client
|
||||
against the live server"). For visual test once B.4b lands:
|
||||
|
||||
```powershell
|
||||
$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
|
||||
$env:ACDREAM_LIVE = "1"
|
||||
$env:ACDREAM_TEST_HOST = "127.0.0.1"
|
||||
$env:ACDREAM_TEST_PORT = "9000"
|
||||
$env:ACDREAM_TEST_USER = "testaccount"
|
||||
$env:ACDREAM_TEST_PASS = "testpassword"
|
||||
$env:ACDREAM_DEVTOOLS = "1"
|
||||
$env:ACDREAM_PROBE_BUILDING = "1"
|
||||
$env:ACDREAM_PROBE_RESOLVE = "1"
|
||||
dotnet run --project src\AcDream.App\AcDream.App.csproj -c Debug 2>&1 |
|
||||
Tee-Object -FilePath "launch-l2g+b4b.log"
|
||||
```
|
||||
|
||||
Then walk into the Holtburg inn doorway, double-left-click the door,
|
||||
wait for the swing animation, walk through. After 30s, watch the
|
||||
auto-close fire.
|
||||
|
||||
After closing the client:
|
||||
|
||||
```powershell
|
||||
Select-String -Path launch-l2g+b4b.log -Pattern "setstate-hex|setstate.*guid|entity-source.*Door|input.*SelectDblLeft"
|
||||
```
|
||||
|
||||
Expected matches:
|
||||
- One `[setstate-hex] body.len=16 ...` line (confirms holtburger's 12-byte payload).
|
||||
- One `[entity-source] name=Door ... state=0x00000000 flags=None ...` at spawn.
|
||||
- An `[input] SelectDblLeft Press` when you double-click.
|
||||
- A `[setstate] guid=0x000F... state=0x????????` after the door opens.
|
||||
- A second `[setstate] guid=0x000F... state=0x00000000` ~30s later when auto-close fires.
|
||||
|
||||
---
|
||||
|
||||
## Worktree state at handoff
|
||||
|
||||
- Branch `claude/gallant-mestorf-3bf2e3` ready to merge to main.
|
||||
- 6 commits ahead of main: `2c10dd4` (spec + docs), `869677b` (plan),
|
||||
`2459f28` / `d538915` / `536a608` / `108e386` (L.2g slice 1 code).
|
||||
- One launch.log artifact (`launch-l2g-slice1.log`) in the working
|
||||
tree from the attempted visual test — **not committed** (gitignored
|
||||
or transient). Safe to discard; B.4b will produce a fresh log.
|
||||
|
||||
User wants to start a fresh session for B.4b.
|
||||
Loading…
Add table
Add a link
Reference in a new issue