fix(physics): P5 commit 3 - retire TS-35, close #167 (ConstraintManager leash)
PhysicsBody.IsFullyConstrained now reflects real ConstraintManager state (pushed every tick by the same per-tick pumps commit 2 wired), so jump_is_allowed's already-ported gate (WeenieError 0x47) actually fires while an object is rubber-banding hard against a server position correction, closing the last piece of #167. Housekeeping: - Delete register row TS-35 (retired: the write side is no longer stubbed). - Rewrite the stale doc comments on PhysicsBody.IsFullyConstrained, ConstraintManager (class + IsFullyConstrained), PositionManager.ConstrainTo, EntityPhysicsHost.PositionManager, and PlayerMovementController.PositionManager that described the leash as permanently unarmed/stubbed. - Close #167 in ISSUES.md citing the research doc and commitse0629145/7719d25b. - Add an "as-ported" addendum to docs/research/2026-07-30-constraint-leash-constants.md naming the actual current seam owners (the doc's own open question flagged this as implementer-verify-required post-J-slices). - Update docs/plans/2026-07-29-physics-parity-campaign.md's P5 status and CLAUDE.md's Campaign P summary to reflect #167's closure (items #153/#72 remain open in P5). Verification: complete solution suite green - 9,978 tests, 5 skips, 0 failures across all 9 test projects (Core.Tests, Runtime.Tests, App.Tests, Headless.Tests, Core.Net.Tests, Content.Tests, UI.Abstractions.Tests, Bake.Tests, Cli.Tests).
This commit is contained in:
parent
7719d25bc5
commit
9e17554ed4
10 changed files with 159 additions and 48 deletions
|
|
@ -94,3 +94,52 @@ None for the constants/flow. Remaining implementation risk is only
|
|||
where acdream's position-acceptance seams sit today (J6.3 moved
|
||||
teleport correlation into Runtime — the implementer must find the
|
||||
current owner rather than trusting older file cites).
|
||||
|
||||
## As-ported (Campaign P Slice P5, 2026-07-30)
|
||||
|
||||
The implementation risk flagged above resolved to these CURRENT seam owners
|
||||
(post-J-slices) — recorded here so the next reader doesn't have to re-derive
|
||||
them:
|
||||
|
||||
- **Constants** — `src/AcDream.Core/Physics/Motion/ConstraintDistance.cs`.
|
||||
Keyed purely on the object's own full cell id's low 16 bits (`>= 0x0100` =
|
||||
indoor); the vestigial player/remote branch from §1 is deliberately not
|
||||
represented as an API parameter.
|
||||
- **Remote arm** — `src/AcDream.App/Physics/LiveEntityNetworkUpdateController.cs`,
|
||||
the inbound `UpdatePosition` handler's remote branch (`update.Guid !=
|
||||
_playerServerGuid`), immediately after the `remotePlacementRequired`
|
||||
hard-teleport block returns (that block already covers retail's
|
||||
`MoveOrTeleport` Branch A / hard-place case; everything reached past it is
|
||||
"did not hard-place"). One call site covers BOTH player-remote and NPC
|
||||
remotes — retail's `SmartBox::HandleReceivedPosition` doesn't distinguish
|
||||
them either, only `GetStart/MaxConstraintDistance`'s now-omitted vestigial
|
||||
branch did. Anchored to the live `IPhysicsObjHost.Position` (which reads
|
||||
`RemoteMotion.Body.Position` + the tracked cell id), matching retail's
|
||||
"anchored to the object's own current position" — since the anchor and
|
||||
`_host.Position` read are the same value at call time,
|
||||
`ConstraintManager.ConstrainTo`'s initial offset is always 0 regardless of
|
||||
whether the routing above just far-snapped or left a near-correction
|
||||
queued.
|
||||
- **Remote per-tick taper + `IsFullyConstrained` push** — already wired
|
||||
pre-P5 for the taper (`RuntimeRemotePhysicsUpdater.Tick`/`TickHidden` call
|
||||
`PositionManager.AdjustOffset` every tick via the pre-existing R5-V3
|
||||
sticky/constraint chain); P5 added the `PhysicsBody.IsFullyConstrained =
|
||||
host.PositionManager.IsFullyConstrained()` push at the same two call
|
||||
sites, since `MotionInterpreter` only holds a `PhysicsBody` (no host
|
||||
reference) and needs a live value to read.
|
||||
- **Local player arm** — `src/AcDream.Runtime/Gameplay/PlayerMovementController.cs`:
|
||||
`SetPositionCore` (teleport: `UnConstrain` then re-`ConstrainTo` after the
|
||||
existing `StopCompletelyAtPhysicsObjectBoundary` velocity zero — composed,
|
||||
not duplicated) and `CommitPreparedPosition` (mirrors the same pair for
|
||||
the deferred player-mode-entry commit path); `BlipPosition` (ForcePosition:
|
||||
`ConstrainTo` only, no teardown — matches `SmartBox::BlipPlayer` surviving
|
||||
motion/velocity/stick). Anchored to `_body.CellPosition` (the just-applied
|
||||
received position).
|
||||
- **Local player per-tick taper + push** — `PlayerMovementController.Update`
|
||||
already called `PositionManager.AdjustOffset` every physics tick pre-P5;
|
||||
P5 added the `_body.IsFullyConstrained = PositionManager?.IsFullyConstrained()
|
||||
?? false` push immediately after, at the same chokepoint.
|
||||
- **TS-35 retirement** — `PhysicsBody.IsFullyConstrained` stayed a plain
|
||||
settable bool (not a computed property) so the ~40 pre-existing direct-set
|
||||
unit tests keep working; the per-tick pumps above are its single writers
|
||||
now, matching the project's per-entity single-owner-write pattern.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue