feat(#184): remote-creature de-overlap — placement-snap + shadow-follows-resolved (visual gate passed)
Packed monster remotes interpenetrate in acdream but barely in retail on the same ACE. Retail de-overlaps them CLIENT-side: it sweeps every remote creature every tick against neighbours' LIVE resolved positions (the collision shadow == the resolved m_position, re-registered every moved transition step), with the server position a gentle catch-up target (CPhysicsObj::MoveOrTeleport 0x00516330), not a hard-snap. The collision math was already faithful; the bug was the reconciliation (hard-snap) + the movement model (synth-velocity) + a stale shadow. A first attempt (reverted) enqueued EVERYTHING and left the shadow at the raw server position — it gate-failed with invisible monsters (an unplaced body blipped over a huge distance into the sweep -> garbage pos) and the player stuck on offset shadows. This redo fixes both root causes, mechanism-proven in a Core test first: - NPC UpdatePosition routes through MoveOrTeleport with a PLACEMENT-SNAP: the body is snapped to the server pos when it is not already near it (first UP, no Sequencer to consume the queue, >96 m, or |Body - worldPos| > 4 m); only near DR corrections enqueue. This restores the body's placement authority (no invisible monsters). Airborne keeps the authoritative hard-snap. - Grounded movement drives the body from the interp CATCH-UP (ComputeOffset -> InterpolationManager::adjust_offset, REPLACE dichotomy) instead of synth-velocity (get_state_velocity / SERVERVEL); MovementManager::UseTime runs unconditionally. - SHADOW-FOLLOWS-RESOLVED: after each tick's sweep the collision shadow is re-registered at the resolved body (SyncRemoteShadowToBody), movement-gated (|Body - LastShadowSyncPos| > 1 cm). The per-UP :5669 raw-pos sync is now PLAYERS-ONLY, so an NPC's shadow is only ever written to its resolved body -> neighbours de-overlap against resolved bodies, the spread PERSISTS, and collision == render (no stuck-on-nothing). Landing clears the interp queue. Preserved: airborne path, sticky #171 (gate + StickyManager overwrite of the seeded frame), omega, the #173 bounce, landing, the node_fail_counter watchdog, and Path A (player remotes, untouched -- Slice 2 unifies it). Tests (RemoteDeOverlapMechanismTests): converging pair settles STABLE at 0.86 m (barely overlapping = the retail look) WITH the shadow-sync vs <0.40 m (full overlap) WITHOUT it; a third test drives the REAL InterpolationManager loop and confirms the sweep absorbs the stall-blip (no pop-into-neighbour). 2-lens Opus review (CONCERNS) addressed: movement-gated re-flood for the town-FPS risk; players-only :5669; the blip-absorption test. Register: retires TS-41 (SERVERVEL synth-velocity -> catch-up), narrows TS-44 (NPC UP unified onto the interp queue; gate kept for orientation), adds AP-86 (shadow-follows-resolved impl) + AP-87 (MoveOrTeleport 4 m/no-Sequencer placement snap). Known residual: the de-overlap sweep uses the human sphere for the mover, so large creatures de-overlap at human radii (TS-46; Slice 3 plumbs Setup dims). Visual gate PASSED (user: monsters visible + spacing much better). Core 2620 / App 741 green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7f7a78d3ea
commit
37a94e1fa4
4 changed files with 558 additions and 99 deletions
|
|
@ -46,6 +46,51 @@ Copy this block when adding a new issue:
|
|||
|
||||
---
|
||||
|
||||
## #184 — Remote monsters overlap (arms interpenetrating) in a crowd; retail barely overlaps
|
||||
|
||||
**Status:** IN-PROGRESS (redo implemented + reviewed — awaiting the user visual re-gate)
|
||||
**Severity:** MEDIUM
|
||||
**Filed:** 2026-07-07
|
||||
**Component:** physics / remote dead-reckoning
|
||||
|
||||
**Description:** Side-by-side vs retail on the SAME ACE, monsters packed around the player
|
||||
interpenetrate (arms) in acdream where retail keeps them barely overlapping — the "no room to
|
||||
slide out" feel. This is the REMOTE-creature thread — distinct from #182 (the LOCAL-player wedge).
|
||||
|
||||
**Root cause / status:** Retail de-overlaps remotes CLIENT-side: it runs the collision sweep on
|
||||
every remote every tick against neighbours' LIVE resolved positions (the shadow == the resolved
|
||||
`m_position`, re-registered every moved step), with the server pos a GENTLE catch-up target
|
||||
(`MoveOrTeleport` 0x00516330), not a hard-snap. **A first attempt (commit `9c0849dd`) GATE-FAILED
|
||||
(invisible monsters + player stuck on them) and was REVERTED** — it (a) replaced the NPC UP
|
||||
hard-snap with enqueue-everything, losing the body's PLACEMENT authority (an unplaced body blipped
|
||||
over a huge distance into the sweep → garbage pos → invisible), and (b) left the shadow at the raw
|
||||
server pos, so neighbours de-overlapped against overlapping shadows and the player collided with an
|
||||
offset shadow. **REDO (this session):** (1) NPC UP `MoveOrTeleport` with a PLACEMENT-SNAP (snap when
|
||||
the body isn't already near the target — first UP / no-Sequencer / far / >4 m; enqueue only near);
|
||||
(2) grounded movement = interp catch-up feeding the kept sweep; (3) **shadow-follows-resolved** —
|
||||
the shadow is re-registered at the resolved body every moving tick (`SyncRemoteShadowToBody`,
|
||||
movement-gated; `:5669` raw sync now players-only). Retires TS-41, narrows TS-44, adds AP-86/AP-87.
|
||||
Mechanism proven in Core (`RemoteDeOverlapMechanismTests`: with-sync 0.86 m stable / without <0.40 m;
|
||||
the real-interp loop absorbs the stall-blip). 2-lens Opus review CONCERNS → all addressed
|
||||
(movement-gate for the town-FPS risk; players-only `:5669`; the blip-absorption test). Core 2620 /
|
||||
App 741 green.
|
||||
|
||||
**Known residual:** the de-overlap sweep uses the fixed human sphere (R 0.48) for the mover, so
|
||||
large packed creatures de-overlap at human radii (**TS-46**; Setup-derived dims = Slice 3).
|
||||
|
||||
**Files:** `src/AcDream.App/Rendering/GameWindow.cs` (NPC `OnLivePositionUpdated` ~:5960 MoveOrTeleport
|
||||
+ shadow sync; Path B tick catch-up/sweep/shadow-sync; `SyncRemoteShadowToBody`).
|
||||
|
||||
**Research:** design `docs/superpowers/specs/2026-07-07-remote-creature-deoverlap-design.md`; handoff
|
||||
`docs/research/2026-07-07-remote-creature-deoverlap-handoff.md`; digest `claude-memory/project_physics_collision_digest.md` (2026-07-07 top).
|
||||
|
||||
**Acceptance:** side-by-side vs retail — packed monsters spread to retail spacing (arms no longer
|
||||
interpenetrating), monsters VISIBLE (not stuck-on-nothing), no ~3 Hz jitter in a pack, no town-FPS
|
||||
drop; remotes don't rubber-band/desync; sticky #171 facing unbroken; walk/run/jump/land unchanged.
|
||||
Then Slice 2 (unify Path A + `RemotePhysicsUpdater` extraction) and Slice 3 (Setup-derived sphere).
|
||||
|
||||
---
|
||||
|
||||
## #183 — Floating distant scenery: trees from another biome hover in the distance
|
||||
|
||||
**Status:** OPEN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue