acdream/memory/project_collision_port.md

11 KiB
Raw Blame History

Collision System Port - Status and Plan

2026-08-03 production cutover stabilization checkpoint

Production initial Create placement is cut over through the Runtime residence and continuation-executor path. The O(changed) collision-publication checkpoint is live, followed by five root-cause fixes:

  • 01f4791e: pending-only live projections no longer create/replay a second origin-recenter retirement receipt;
  • 670f307c: remote Create placement, local-player hosting, targeting, chase, and attack share the same world-coordinate frame;
  • 1fc529cd: distant Use materializes the canonical minimal static host before MoveTo;
  • f24532ad: effects, projectiles, and static animation bind after canonical placement and follow the committed cell;
  • 175ad6b0: LoginComplete waits for the local first-placement terminal edge.

The user accepted those connected behaviors. The campaign remains open for six fixture reconciliations, C4 placement routes 27, #276/#277, destination prefetch #280, C5's final-binary suite/soak/two-client matrix, AP-22, and AD-10. Canonical continuation prompt: docs/research/2026-08-02-collision-throughput-handoff/NEXT-AGENT-PROMPT.md.

Do not use the 2026-04-29 whole-world staging-root description below as a production blueprint. It is retained as historical context. O1/O2/O3 at 71604331 replaced that clone/journal/rebase design with the per-landblock O(changed) publication mechanism; 01f4791e then repaired its recenter receipt lifetime.

2026-08-01 initial Create residence checkpoint

Historical checkpoint; superseded by the 2026-08-03 production cutover status above.

The dormant Runtime SetPosition path is now complete through activation, graphical/no-window placement receipts, collision-prefix quiescence, exact authoritative route classification, pre-placement App staging, and initial Create residence. Commit 38fd4b8d owns the accepted initial Create frame, cell-less pending lifetime, fresher Position FIFO, exact completion/adoption revision, and reentrant teardown. Its retail and continuation handoff is:

  • docs/research/2026-08-01-runtime-initial-create-residence-handoff.md

Production Create registration has not yet been cut over. Next, implement the synchronous Runtime continuation executor and exact Create tail order (visual, Parent/Position/Pickup, Movement, State, Vector, WeenieDesc, cleanup), then cut graphical and no-window hosts over together. AP-1/AD-1 remain open until that cutover. AP-22 and AD-10 follow as separate behavior slices.

2026-07-31 placement checkpoint 2

Runtime now owns the retail collision-report state required by canonical SetPosition: exact-incarnation object-contact tables, the environment latch, ordinary/ethereal expiry, force-end ordering, asymmetric object/environment report eligibility, missile-state clearing, reentrant ordered reports, and the report-result boolean which distinguishes failed-placement Collided from NoValidPosition. Successful dormant SetPosition commits reporting after contact/ground state and before its one response plus shadow reflood. The named-retail oracle and next-agent instructions are in:

  • docs/research/2026-07-31-runtime-set-position-collision-reporting.md
  • docs/research/2026-07-31-runtime-set-position-collision-reporting-handoff.md

This checkpoint deliberately does not activate production placement. Next, 4B2 must prepare exact authored movers and land one atomic Runtime body/local- controller transaction, followed by presentation-only host projection, collision-prefix quiescence, and an all-route cutover. AP-1 and AD-1 remain open until that cutover; AP-22 and AD-10 remain later campaign slices.

Current State (2026-04-29)

The collision system is no longer a pure placeholder and should not be treated as "delete everything and start over." A partial retail transition port exists:

  • PhysicsEngine.ResolveWithTransition is the active player movement resolver.
  • BSPQuery contains a partial retail-style BSP dispatcher.
  • TransitionTypes carries the active SpherePath, CollisionInfo, transition, step, contact, and partial slide logic.
  • PhysicsDataCache loads GfxObj, Setup, and CellStruct physics data.
  • Landblock streaming never edits the live collision world incrementally. PreparedLandblockCollisionGeneration owns an off-side cache, CellGraph, engine snapshot, buildings, statics, and versioned retained-owner refloods. Retained means every non-suspended dynamic or adjacent-root static touching (or withdrawn from) the target prefix; only authored target-root statics are superseded. Stable per-prefix owner slots bound capture independently of unrelated movement. One Runtime-scoped versioned journal records a live mutation once, coalesces repeated changes by owner, and lets every draft reconcile only that owner's latest exact state one owner per seal step. Relevant owners subscribe only after discovery, preserving exact continuous updates without the former preparations-by-mutations global fanout or a quiet frame. A changed prefix routes first target entry/departure to the one matching draft after its journal cursor has passed. During topology build, visited unrelated owners receive only coalesced dirty notifications; one later seal unit performs the exact mirror. After the topology seal exists, observed owners temporarily write through exactly until same-call activation, guaranteeing that the finite dirty queue drains under multi-owner motion. Old slots are superseded at the tail rather than reused behind live cursors, new drafts start at their captured suffix, and obsolete slots plus empty prefix containers are reclaimed under churn. Admission captures the active aggregate root reference in O(1), then stable landblock/owner suffixes materialize the non-target cache, CellGraph, engine, and shadow leaves one work unit per host step. All scans and replacement construction run through bounded preparation/capture/seal cursors. Cache, CellGraph, engine, and shadow topology share one complete off-side CollisionWorldState; final activation is a single zero-allocation volatile root transfer that preserves borrowed facade identities and revokes staging. Deterministically ordered concurrent preparations queue their deltas into later drafts only after commit; each seal call rebases at most one cache/graph/landblock/owner leaf. Demotion or withdrawal cancels matching queued/active rebases, suppresses stale source- clone leaves, and retires one owner/cache/graph/outdoor leaf per seal step from growable storage; commit rechecks pending retirement after sealing. The host performs the zero-work root transfer in the same update-thread call that completes final reconciliation, avoiding a quiet-frame requirement. Cancellation tears down only the named staging generation. The old generation remains queryable until commit. See docs/research/2026-07-31-atomic-collision-generation.md.
  • ShadowObjectRegistry gives the resolver a broadphase over nearby objects.
  • TerrainSurface uses triangle-aware terrain contact.

This foundation is useful, but it is not complete retail collision parity. The project now tracks the remaining work as Phase L.2 - Movement & Collision Conformance:

  • Plan: docs/plans/2026-04-29-movement-collision-conformance.md
  • Roadmap owner: docs/plans/2026-04-11-roadmap.md
  • Tactical follow-ups: docs/ISSUES.md #30-#34

Durable Lesson

Do not guess at AC physics, movement packets, terrain/cell ownership, or collision constants. The previous patchwork failures came from simplified approximations:

  • static overlap instead of swept-sphere transition behavior
  • custom object collision instead of retail CSphere / CCylSphere
  • incomplete BSP dispatch
  • ad-hoc push-out instead of retail slide / edge / precipice handling
  • server "no rubber-band" treated as proof of local collision correctness

The named retail decomp is now the primary source. Search docs/research/named-retail/acclient_2013_pseudo_c.txt by class::method before using older decompiled chunks or reference repos.

Active Approach

Continue by conformance lanes rather than rewriting blindly:

  1. Truth & diagnostics (L.2a). Add local placement/contact/cell, object-hit, outbound-packet, server echo, and correction-delta probes.
  2. Movement wire/contact authority (L.2b). Fix contact byte and full-cell truth before using ACE acceptance as evidence.
  3. Transition parity (L.2c). Port edge-slide, cliff-slide, precipice-slide, step-up/down slide, and NegPolyHit dispatch.
  4. Shape fidelity (L.2d). Finish CSphere / CCylSphere semantics, live-entity shapes, and building object identity.
  5. Cell ownership (L.2e). Port CELLARRAY, find_cell_list, check_other_cells, adjust_check_pos, low-cell updates, and cell_bsp.
  6. Real-DAT and live observer conformance (L.2f). Promote every synthetic case to real-world fixtures and retail-observer checks.

What To Preserve

  • CollisionPrimitives.cs low-level helpers, while auditing remaining shape gaps against named retail.
  • PhysicsDataCache.cs DAT-backed collision data loading.
  • ShadowObjectRegistry.cs broadphase concept.
  • TransitionTypes.cs data structures and partial transition port.
  • BSPQuery.cs partial dispatcher as the current porting surface.
  • PhysicsBody.cs, MotionInterpreter.cs, and PlayerWeenie.cs foundations.

Known Gaps

  • Full CELLARRAY and adjacent-cell ownership are missing.
  • cell_bsp is not yet a first-class runtime owner.
  • Building portal transit and building entry/exit collision are incomplete.
  • edge_slide, cliff_slide, precipice_slide, and NegPolyHit behavior are incomplete.
  • Live entity shape fidelity is simplified.
  • Outbound movement contact/cell fields can be overconfident.
  • Routine local/server correction diagnostics are missing.

Retail Anchors

Primary:

  • docs/research/named-retail/acclient_2013_pseudo_c.txt
  • docs/research/named-retail/acclient.h
  • docs/research/named-retail/symbols.json

Key names:

  • CTransition::find_transitional_position
  • CTransition::transitional_insert
  • CTransition::step_up
  • CTransition::step_down
  • CTransition::edge_slide
  • CTransition::cliff_slide
  • SPHEREPATH::step_up_slide
  • SPHEREPATH::precipice_slide
  • SPHEREPATH::adjust_check_pos
  • CTransition::check_other_cells
  • CObjCell::find_cell_list
  • CPhysicsObj::is_valid_walkable
  • CBuildingObj::find_building_collisions
  • CCellStruct::sphere_intersects_cell
  • CCylSphere::intersects_sphere
  • CSphere::intersects_sphere
  • CSphere::slide_sphere

Older fallback:

  • docs/research/decompiled/chunk_00530000.c
  • docs/research/decompiled/chunk_00500000.c
  • docs/research/acclient_function_map.md

Reference aids:

  • references/ACE/Source/ACE.Server/Physics/
  • references/holtburger/ for movement wire behavior
  • references/AC2D/ for the older client-side movement packet reference

Mandatory Workflow

For every AC-specific function:

  1. Grep named retail first.
  2. Cross-reference ACE / holtburger / AC2D where relevant.
  3. Write readable pseudocode before porting.
  4. Port faithfully; do not simplify.
  5. Add conformance tests.
  6. Integrate surgically into the active L.2 lane.
  7. Verify with synthetic tests, real-DAT fixtures, and live observer evidence.