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:
parent
e44d24cec6
commit
d4c3f947d2
6 changed files with 689 additions and 242 deletions
|
|
@ -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 | — |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue