docs(physics): Phase L.2 movement collision conformance plan

Formalize Phase L.2 as the active holistic movement/collision program, align the roadmap and architecture docs, file tactical physics follow-ups, and refresh collision memory away from rewrite-from-zero guidance.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-04-29 21:28:56 +02:00
parent e44d24cec6
commit d4c3f947d2
6 changed files with 689 additions and 242 deletions

View file

@ -100,67 +100,129 @@ crib-sheet version.
---
## Project Structure (target)
## Project Structure (current + target)
```
src/
AcDream.Core/ Layer 2-4: no GL, no Silk.NET, pure logic
Physics/
PhysicsBody.cs ← ported from decompiled (done)
CollisionPrimitives.cs ← ported from decompiled (done)
MotionInterpreter.cs ← ported from decompiled (done)
AnimationSequencer.cs ← ported from decompiled (done)
CellBsp.cs ← TODO: port from decompiled
Transition.cs ← TODO: port from decompiled
TerrainSurface.cs ← verified against ACME (done)
PhysicsBody.cs -> body state / integration foundation (done)
CollisionPrimitives.cs -> retail primitive helpers (partial, active)
MotionInterpreter.cs -> motion state machine (done, still L.1 polish)
AnimationSequencer.cs -> animation playback + root-motion data (done, L.1 active)
TerrainSurface.cs -> triangle-aware terrain contact (done)
BSPQuery.cs -> partial retail BSP dispatcher (active in L.2)
TransitionTypes.cs -> SpherePath / CollisionInfo / transition helpers (active in L.2)
PhysicsDataCache.cs -> GfxObj / Setup / CellStruct collision data (done, active)
ShadowObjectRegistry.cs -> broadphase for nearby physics objects (active)
PhysicsEngine.cs -> ResolveWithTransition active player path
CellBsp.cs -> not a first-class runtime owner yet (L.2e)
World/
GameEntity.cs ← TODO: unified entity (replaces scattered state)
WorldState.cs ← TODO: owns all entities
CellTracker.cs ← TODO: per-entity cell management
SceneryGenerator.cs verified against decompiled (done)
LandblockLoader.cs done
GameEntity.cs -> target unified entity, not current reality
WorldState.cs -> target entity owner
CellTracker.cs -> target per-entity cell management
SceneryGenerator.cs -> verified against decompiled (done)
LandblockLoader.cs -> done
Terrain/
LandblockMesh.cs verified against ACME (done)
TerrainBlending.cs verified against ACME (done)
LandblockMesh.cs -> verified against ACME (done)
TerrainBlending.cs -> verified against ACME (done)
Meshing/
GfxObjMesh.cs cross-checked against ACME (done)
SetupMesh.cs cross-checked (done)
GfxObjMesh.cs -> cross-checked against ACME (done)
SetupMesh.cs -> cross-checked (done)
Textures/
SurfaceDecoder.cs done
SurfaceDecoder.cs -> done
Dat/
MotionResolver.cs ← done (move here from Meshing/)
MotionResolver.cs -> done (target move from Meshing/)
AcDream.Core.Net/ Layer 2: networking
WorldSession.cs done (wire-compatible with ACE)
NetClient.cs done
Messages/ done (CreateObject, MoveToState, etc.)
WorldSession.cs -> done (wire-compatible with ACE)
NetClient.cs -> done
Messages/ -> done (CreateObject, MoveToState, etc.)
AcDream.Plugin.Abstractions/ Layer 5: plugin interfaces
IAcDreamPlugin.cs done
IPluginHost.cs done
IGameState.cs done
IEvents.cs done
IAcDreamPlugin.cs -> done
IPluginHost.cs -> done
IGameState.cs -> done
IEvents.cs -> done
AcDream.App/ Layer 1 + Layer 4 wiring
Rendering/
GameWindow.cs ← TODO: thin down to GL calls only
TerrainRenderer.cs done
StaticMeshRenderer.cs done
TextureCache.cs done
ChaseCamera.cs done
FlyCamera.cs done
GameWindow.cs -> still owns too much runtime wiring
TerrainRenderer.cs -> done
StaticMeshRenderer.cs -> done
TextureCache.cs -> done
ChaseCamera.cs -> done
FlyCamera.cs -> done
Streaming/
StreamingController.cs done
GpuWorldState.cs done
StreamingController.cs -> done
GpuWorldState.cs -> done
Input/
PlayerMovementController.cs ← done (uses ported physics)
PlayerMovementController.cs -> active movement driver
Plugins/
AppPluginHost.cs done
AppPluginHost.cs -> done
```
---
## GameEntity: The Unified Entity (TODO — the big refactor)
## Movement And Collision Architecture
Phase L.2 is the current organizing program for physics, collision,
boundaries, buildings, sliding, cell ownership, movement packets, and server
authority. Detailed plan: `docs/plans/2026-04-29-movement-collision-conformance.md`.
The active player movement spine is:
```text
InputDispatcher / PlayerMovementController
-> MotionInterpreter + local body prediction
-> PhysicsEngine.ResolveWithTransition
-> TransitionTypes + BSPQuery + ShadowObjectRegistry
-> ResolveResult contact/cell state
-> MoveToState / AutonomousPosition outbound messages
-> WorldSession server echo or correction handling
```
What exists and is active:
- `PhysicsEngine.ResolveWithTransition` is the path used for local player
collision resolution.
- `BSPQuery` contains the partial retail-style BSP collision dispatcher used by
the transition path.
- `TransitionTypes` carries `SpherePath`, `CollisionInfo`, `ObjectInfo`,
transition validation, step-up/down, contact-plane handling, and partial
slide behavior.
- `PhysicsDataCache` loads GfxObj, Setup, and CellStruct physics data from DATs.
- `ShadowObjectRegistry` gives movement a broadphase over nearby objects and
buildings.
- `TerrainSurface` uses triangle-aware terrain contact; older "bilinear terrain
Z" descriptions are historical B.3 language, not current architecture.
What remains incomplete:
- `CELLARRAY`, `CObjCell::find_cell_list`, adjacent-cell checks, and low outdoor
cell id updates across 24m seams.
- `cell_bsp` / `CellBSP` as the authoritative runtime owner for indoor and
building collision.
- Building portal transit and normal walking through building entry/exit
boundaries.
- Full retail `edge_slide`, `cliff_slide`, `precipice_slide`, and `NegPolyHit`
dispatch behavior.
- Exact `CSphere` / `CCylSphere` object-shape parity, especially for live
entities that currently collapse to a simplified cylinder fallback.
- Routine local/server correction diagnostics. ACE accepting a position is a
compatibility signal, not proof of fine retail collision parity.
Ownership by phase:
- B.3 is shipped MVP history: first resolver foundation and tests.
- L.1 owns animation/motion parity, including root-motion coupling.
- L.2 owns the movement/collision conformance stack listed above.
- G.3 owns dungeon streaming and portal-space delivery after L.2e gives it
trustworthy cell/building boundaries.
---
## GameEntity: The Unified Entity (target refactor)
Currently, entity state is scattered across:
- `WorldEntity` (position, rotation, mesh refs)
@ -198,21 +260,21 @@ public sealed class GameEntity
{
Motion.ApplyCurrentMovement(); // set velocity from motion state
Physics.UpdateObject(dt); // integrate position
// TODO: Transition.FindValidPosition // collision resolve
Cell.UpdateCell(Physics.Position); // check cell transitions
PhysicsEngine.ResolveWithTransition(); // current L.2 collision spine
Cell.UpdateCell(Physics.Position); // target: retail cell ownership
Animation.Advance(dt); // advance animation frames
RebuildMeshRefs(); // compute per-part transforms
}
}
```
Every entity in the world — player, NPC, monster, lifestone, door, chest —
is a `GameEntity`. The renderer iterates them and draws. The plugin API
exposes them as `WorldEntitySnapshot`. GameWindow becomes thin.
Target state: every entity in the world — player, NPC, monster, lifestone,
door, chest — becomes a `GameEntity`. The renderer iterates them and draws.
The plugin API exposes them as `WorldEntitySnapshot`. GameWindow becomes thin.
---
## Per-Frame Update Order (matches retail)
## Per-Frame Update Order (current runtime)
```
1. Network tick
@ -224,15 +286,16 @@ exposes them as `WorldEntitySnapshot`. GameWindow becomes thin.
create terrain + scenery GameEntities
3. Input tick (player mode only)
└── Read WASD/mouse → MotionInterpreter.DoMotion →
└── InputDispatcher scopes → PlayerMovementController →
MotionInterpreter/body prediction → ResolveWithTransition →
send MoveToState/AutonomousPosition to server
4. Entity tick (ALL entities, 30Hz fixed step)
└── For each GameEntity: entity.Update(dt)
This runs: motion → physics → collision → cell → animation
4. Entity / animation tick
└── Current code still has scattered world/entity state. L.1 owns
animation parity; L.2 owns movement/collision conformance.
5. Render tick
└── For each GameEntity: read MeshRefs, draw
└── Read current entity mesh refs, draw
TerrainRenderer.Draw, StaticMeshRenderer.Draw
(frustum cull, translucency pass, etc.)
@ -248,89 +311,26 @@ exposes them as `WorldEntitySnapshot`. GameWindow becomes thin.
---
## Execution Plan: How to Get There
## Roadmap Model
### Phase R1: GameEntity Refactor (the foundation)
**Goal:** Replace the scattered entity state with unified GameEntity.
The old R1-R8 architecture sequence was a useful early refactor sketch, but it
is no longer the execution plan. The strategic source of truth is now
`docs/plans/2026-04-11-roadmap.md`, with per-phase details in `docs/plans/`
and `docs/superpowers/specs/`.
1. Create `GameEntity` class in `AcDream.Core/World/`
2. Move `AnimatedEntity` fields into `GameEntity.Animation`
3. Move `WorldEntity` fields into `GameEntity.Physics` + position
4. Move `_entitiesByServerGuid` into `WorldState`
5. Move animation tick from `GameWindow.TickAnimations` into `GameEntity.Update`
6. GameWindow.OnRender reads `GameEntity.MeshRefs` instead of `WorldEntity.MeshRefs`
Current movement/collision ownership:
**Test:** Everything looks the same as before. No visual change.
- **B.3** is shipped MVP history: first collision resolver foundation.
- **L.1** owns animation/motion parity, including root-motion coupling.
- **L.2** owns movement and collision conformance:
`docs/plans/2026-04-29-movement-collision-conformance.md`.
- **G.3** owns dungeon streaming and portal-space delivery after L.2e lands
trustworthy `cell_bsp`, `CELLARRAY`, adjacent-cell checks, and building
entry/exit boundaries.
### Phase R2: Thin GameWindow
**Goal:** GameWindow does only GL calls + input dispatch.
1. Extract entity creation from `OnLiveEntitySpawned` into `WorldState.SpawnEntity`
2. Extract motion updates from `OnLiveMotionUpdated` into `WorldState.UpdateMotion`
3. Extract player movement from the giant OnUpdate block into `PlayerController`
4. GameWindow.OnUpdate calls: network.Tick → streaming.Tick → input.Tick → worldState.Tick → render
**Test:** Everything works the same. GameWindow.cs drops from 2000+ to ~500 lines.
### Phase R3: CellBSP + Wall Collision
**Goal:** Entities can't walk through walls.
1. Port CellBSP from decompiled code (sphere_intersects_cell)
2. Port Transition.FindValidPosition (swept sphere collision)
3. Wire into GameEntity.Update between physics and cell tracking
4. Indoor transitions become correct (wall stops you, doorway lets you through)
**Test:** Walk into building wall → stopped. Walk through doorway → enter.
### Phase R4: Complete Animation State Machine
**Goal:** Every animation works for every entity type.
1. Port full MotionInterp.PerformMovement from decompiled (all 5 movement types)
2. Port Links table resolution for smooth transitions
3. Port idle modifiers (fidgets)
4. Jump animation (wire jump motion command through the pipeline)
**Test:** All entity types animate correctly. Transitions are smooth.
### Phase R5: Lighting from Retail
**Goal:** Sun, ambient, per-vertex lighting match retail.
1. Port AdjustPlanes (FUN_00532440) — face normals + per-vertex lighting
2. Extract global lighting constants from decompiled DAT addresses
3. Replace hardcoded shader constants with ported values
**Test:** Side-by-side with retail client shows matching lighting.
### Phase R6: Server Compliance
**Goal:** ACE accepts all movement, no rubber-banding.
1. Server-authoritative Z (trust server position, local is cosmetic)
2. Proper MoveToState with full RawMotionState packing
3. Keepalive ping (5s idle)
4. Graceful session management
**Test:** Walk around, other clients see smooth movement. No ACE errors.
### Phase R7: Interaction
**Goal:** Click NPCs, open doors, pick up items, chat.
1. Use/UseWithTarget game actions
2. Door open animation (server sends UpdateMotion → animate)
3. Chat send/receive
4. Basic inventory (pickup/drop)
**Test:** Open a door, talk to an NPC, send a chat message.
### Phase R8: Plugin API Completion
**Goal:** Plugins can observe and control everything.
1. IGameState exposes all GameEntity fields
2. IEvents fires for all world changes
3. IActions covers: Move, Cast, Use, Say, Pickup, Drop
4. IPacketPipeline hooks all 4 stages
5. Lua macro engine (MoonSharp) ships as a built-in plugin
**Test:** A Lua script auto-loots gems. A C# plugin displays an overlay.
The GameEntity / thin GameWindow refactor remains a valid target architecture,
but it is not a prerequisite for L.2. Do not resurrect old R1-R8 phase numbers
for new work; add or update roadmap phases instead.
---
@ -339,11 +339,12 @@ exposes them as `WorldEntitySnapshot`. GameWindow becomes thin.
```
For every AC-specific behavior:
1. DECOMPILE → Find the function in docs/research/decompiled/
2. CROSS-CHECK → Verify against ACE + ACME + holtburger
0. GREP NAMED → Search docs/research/named-retail/ by class::method
1. FALLBACK → Use older docs/research/decompiled/ chunks only if needed
2. CROSS-CHECK → Verify against ACE + ACME + holtburger where relevant
3. PSEUDOCODE → Translate to readable pseudocode
4. PORT → Faithful C# translation
5. TEST → Conformance test against decompiled golden values
5. TEST → Conformance test against retail/decomp golden values
6. INTEGRATE → Surgical wiring into the existing system
7. VERIFY → Visual + functional test
```
@ -359,9 +360,9 @@ For acdream-specific code (renderer, plugin API, streaming):
| Domain | Primary Oracle | Secondary |
|--------|---------------|-----------|
| Physics/collision | Decompiled acclient.exe | ACE Physics/ |
| Animation | Decompiled + ACE Animation/ | — |
| Terrain | ACME ClientReference.cs | Decompiled |
| Physics/collision | `docs/research/named-retail/` | ACE Physics/ + older decompiled chunks |
| Animation | `docs/research/named-retail/` + ACE Animation/ | — |
| Terrain | ACME ClientReference.cs | named retail / older decompiled chunks |
| Rendering | WorldBuilder (Silk.NET) | ACViewer |
| Protocol | holtburger | AC2D |
| Server behavior | ACE | — |