fix(physics): keep remote placement and targeting in one world frame

CreateObject positions are landblock-local, but Runtime first-entry previously submitted remotes with a zero world offset. Runtime now owns the accepted local-player world-frame center and converts remote placements before SetPosition. The local physics host also publishes body.Position rather than CellPosition's landblock-local origin, so TargetManager no longer directs monsters toward a phantom player position. User gate: monster/static placement, chase, and attacks accepted outside Tusker Barracks.
This commit is contained in:
Erik 2026-08-03 08:59:31 +02:00
parent 01f4791e95
commit 670f307c84
7 changed files with 140 additions and 12 deletions

View file

@ -250,7 +250,11 @@ internal sealed class RuntimeFirstEntryDriveController
// Contention — nothing more this pump can do synchronously.
return;
}
if (!TryCompleteContinuationPlacement(key, pending.Record))
if (!TryCompleteContinuationPlacement(
key,
pending.Record,
resolveWorldOffsetFromRuntimeFrame:
!pending.IsLocalPlayer))
return;
// A continuation placement progressed — re-Advance so the
// executor can consume the acknowledged completion and keep
@ -265,7 +269,8 @@ internal sealed class RuntimeFirstEntryDriveController
/// </summary>
private bool TryCompleteContinuationPlacement(
RuntimeEntityKey key,
RuntimeEntityRecord record)
RuntimeEntityRecord record,
bool resolveWorldOffsetFromRuntimeFrame)
{
RuntimeSetPositionState setPosition =
_entityObjects.Physics.SetPosition;
@ -311,7 +316,9 @@ internal sealed class RuntimeFirstEntryDriveController
route.SetPositionFlags,
_collisionSource,
_clock.SimulationTimeSeconds,
out RuntimeSetPositionOutcome outcome);
out RuntimeSetPositionOutcome outcome,
resolveWorldOffsetFromRuntimeFrame:
resolveWorldOffsetFromRuntimeFrame);
if (status != RuntimeSetPositionMoverPreparationStatus.Prepared)
{
// RetrySetupUnavailable retries on a later pump; a rejected