docs(issues): close #42 (self-skip ec59a08), file + close #43 staircase (9e4772a)

#42 — moved from OPEN to DONE in place (rich investigation log preserved
below the new Resolution block). The originally-listed mechanisms (H1
slope-driven AdjustOffset projection, H2 step-down probe, H3 EdgeSlide)
were all RULED OUT by the first evidence run; root cause was self-
collision in FindObjCollisions, not in-sweep mechanism choice. Added
forward-pointer to retail's CObjCell::find_obj_collisions self-skip
(named-retail acclient_2013_pseudo_c.txt:308931).

#43 — new entry in Recently closed for the slope staircase on grounded
player remotes. Diagnosis: PositionManager.ComputeOffset's seqVel-only
fallback returned flat-Z motion because anim cycles bake Z=0 body-local,
producing visible 5 Hz Z stepping at the server-UP cadence. Fix: project
the fallback onto the local terrain plane (mirrors retail's
CTransition::adjust_offset contact-plane projection at the queue-empty
boundary). Verified via 9193 queue-empty-with-non-zero-offset.Z ticks
across a 34m vertical traversal.

Both diagnostic env-vars kept in tree for future regression hunts:
ACDREAM_AIRBORNE_DIAG=1 and ACDREAM_SLOPE_DIAG=1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-05 21:51:12 +02:00
parent 9e4772a8f8
commit 5f2e2e28ff

View file

@ -124,12 +124,52 @@ the same direction. Add a `LastUMUpdateTime` grace window (e.g.
- No spurious cycle thrashing during turning while running (ObservedOmega
doesn't trigger velocity-bucket changes).
## #42 — Airborne XY drift on observed player remote jumps (~1 m horizontal offset over arc)
## #42 [DONE 2026-05-05 · ec59a08] Airborne XY drift on observed player remote jumps (~1 m horizontal offset over arc)
**Status:** OPEN
**Status:** DONE
**Severity:** MEDIUM (pre-existing PhysicsEngine bug; exposed by L.3 M2 airborne UP no-op + M4 CellId fix)
**Filed:** 2026-05-05 (root cause confirmed same day)
**Component:** physics (`PhysicsEngine.ResolveWithTransition` airborne behavior)
**Closed:** 2026-05-05
**Commit:** `ec59a08`
**Component:** physics (`PhysicsEngine.ResolveWithTransition``FindObjCollisions` self-skip)
**Resolution (2026-05-05):** Self-collision in `FindObjCollisions`, not
any of the three originally-hypothesised mechanisms below. Live
entities (local player, remotes) register a Cylinder in
`ShadowObjectRegistry` at spawn (`GameWindow.cs:2545`) which
`UpdatePosition` keeps tracking the entity's live world position.
With no self-skip filter, the moving sphere's own cylinder is always
sitting at the body's exact position and `CylinderCollision` slides
the sphere out of overlap on every airborne tick. Validated by the
[SWEEP-OBJ] diagnostic added in commit `a36369d`: every drift event
showed `gfxObj=0x02000001` (humanoid setup) at `obj.Position` exactly
matching the body's `pre`. Mirrors retail's `CObjCell::find_obj_collisions`
self-skip at named-retail line 308931:
```c
if ((physobj->parent == 0 && physobj != arg2->object_info.object))
result = CPhysicsObj::FindObjCollisions(physobj, arg2);
```
Plumbing: `ObjectInfo.SelfEntityId` field, optional
`movingEntityId = 0` parameter on `ResolveWithTransition`,
`PlayerMovementController.LocalEntityId` refreshed per-tick from
`_entitiesByServerGuid[_playerServerGuid].Id`, remote sweep at
`GameWindow.cs:6474` passes `kv.Key`. Lock-the-fix unit test at
`PhysicsEngineTests.ResolveWithTransition_SelfShadowEntry_NotPushedWhenIdMatches`.
Verified via two visual + log runs (`launch-42-verify.log` /
`launch-42-verify2.log`): zero stationary-jump drift across both,
`gfxObj=0x02000001` phantom no longer appears in `[SWEEP-OBJ]`,
no >0.5m pushes anywhere. The originally-listed hypotheses (H1
slope-driven AdjustOffset projection, H2 step-down probe, H3
EdgeSlide) were all RULED OUT by the first evidence run — `cpN`
was `(0, 0, 1)` flat for every drift event.
**Diagnostic kept in tree:** `ACDREAM_AIRBORNE_DIAG=1` enables the
`[SWEEP]` + `[SWEEP-OBJ]` traces for future regression hunts.
The original investigation log is preserved below for context.
**Root cause (verified 2026-05-05 via A/B test):**
@ -1188,6 +1228,53 @@ If hypothesis (a) is correct, this issue effectively rolls into **#28** — the
# Recently closed
## #43 — [DONE 2026-05-05 · 9e4772a] Slope staircase on observed player remotes (anim-only fallback ignored slope)
**Closed:** 2026-05-05
**Commit:** `9e4772a`
**Component:** motion (`PositionManager.ComputeOffset` queue-empty fallback)
**Resolution:** Grounded player remotes showed a ~5 Hz Z staircase when
running up/down hills. `PositionManager.ComputeOffset` has two modes:
queue-active (3D direction toward server's broadcast position, Z
follows naturally) and queue-empty / head-reached (`seqVel × dt`
rotated into world). Every locomotion cycle bakes Z=0 in body-local,
so the world result has Z=0 too. With server UPs at ~5 Hz and
catchUpSpeed = 2× maxSpeed, body chases each waypoint in ~100ms (Z
ramps), then sits in seqVel-only mode for ~100ms (Z flat) until the
next UP. Visible 5 Hz staircase.
Fix mirrors retail's `CTransition::adjust_offset` contact-plane
projection (named-retail acclient_2013_pseudo_c.txt:272296-272346),
applied at the queue-empty boundary instead of inside the sweep.
`ComputeOffset` gains an optional `Vector3? terrainNormal`; when
the seqVel fallback runs and the supplied normal is non-trivial,
`rootMotionWorld -= N × dot(rootMotionWorld, N)`. XY motion gains a
Z component proportional to slope × forward speed; body Z follows the
terrain mesh between UPs. No-op on flat ground (N ≈ +Z, dot ≈ 0) so
no regression to L.3 M2's flat-ground verification.
`GameWindow.TickAnimations` grounded-remote path samples
`PhysicsEngine.SampleTerrainNormal` (a thin public wrapper over the
existing internal `SampleTerrainWalkable`) at the body's current XY
each tick and passes it to `ComputeOffset`.
Two unit tests in `PositionManagerTests`: 30° east-tilted slope
(asserts `(3.0, 0, 1.732)` for 4 m/s east motion over 1s — body
descends along slope) + flat-ground no-op (asserts unchanged
behaviour with `N = +Z`).
Verified via `launch-slope-verify.log` over a 34m vertical traversal:
9,193 queue-empty-with-non-zero-offset.Z ticks on slopes (the path
that previously stair-cased), 26,497 sloped-normal ticks total, zero
#42 regressions.
**Diagnostic kept in tree:** `ACDREAM_SLOPE_DIAG=1` enables the
`[SLOPE]` per-tick trace (`bodyZ` before/after, offset, queue active,
sampled `cpN.Z`) for future regression hunts.
---
## #31 — [DONE 2026-04-29] Low outdoor cell id can go stale after transition movement
**Closed:** 2026-04-29