acdream/memory/project_collision_port.md

5.7 KiB

Collision System Port - Status and Plan

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. All scans and replacement construction run through bounded capture/seal cursors. RuntimePhysicsState.CommitCollisionGeneration does one final mutation-version check and activates the sealed generation without managed allocation on the single update thread. 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.