fix(interaction): restore distant use after runtime cutover

Runtime GetObjectA lookup became intentionally non-constructing, so static doors and corpses entered MoveToObject without a physics host and their target snapshot timed out at the origin. Ensure the canonical minimal host exists before routing the server move.

Runtime first-entry also grounds the local player before graphical PartArray attachment. That could leave an unmatched startup CMotionInterp node ahead of all later use and cast motion. Drain matched PartArray entries first, then retire only the impossible pre-attach suffix at the presentation attach boundary.

Add focused regressions for static-target host materialization and attach-order reconciliation. User verified near and distant object use in the connected client; focused App tests pass 3/3.
This commit is contained in:
Erik 2026-08-03 09:36:53 +02:00
parent 670f307c84
commit 1fc529cdcb
4 changed files with 183 additions and 1 deletions

View file

@ -417,7 +417,17 @@ internal sealed class LiveEntityMotionRuntimeController
if (update.MotionState.MovementType == 6
&& path.TargetGuid is { } tgtGuid
&& _liveEntities is { } liveMoveEntities
&& liveMoveEntities.TryGetInteractionEligibleEntity(tgtGuid, out var tgtEnt))
&& liveMoveEntities.TryGetInteractionEligibleEntity(tgtGuid, out var tgtEnt)
// Retail resolves the CPhysicsObj itself here. Even a static,
// animation-less object (door, chest, corpse, NPC prop) can
// therefore accept AddVoyeur and immediately publish its
// position. C3c moved the local player's GetObjectA seam into
// Runtime, where lookup is intentionally non-constructing;
// eagerly materialize the existing canonical minimal host at
// this App composition boundary before PerformMovement asks
// Runtime for it. Without this, MoveToObject arms but receives
// no target snapshot and times out at (0,0,0).
&& ResolvePhysicsHost(tgtGuid) is not null)
{
ms.Type = AcDream.Core.Physics.MovementType.MoveToObject;
ms.ObjectId = tgtGuid;