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:
parent
01f4791e95
commit
670f307c84
7 changed files with 140 additions and 12 deletions
|
|
@ -556,6 +556,18 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
Func<RuntimeEntityRecord, Exception?>? retirePriorProjection)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
if (beginInitialResidence
|
||||
&& isLocalPlayer
|
||||
&& (incoming.Physics?.Position ?? incoming.Position)
|
||||
is { LandblockId: not 0u } initialPlayerPosition)
|
||||
{
|
||||
// The accepted local Create establishes the shared world frame
|
||||
// before any remote first-entry conductor converts its authored
|
||||
// landblock-local coordinates.
|
||||
Physics.ObserveLocalWorldFrame(
|
||||
initialPlayerPosition.LandblockId,
|
||||
teleportAdvanced: false);
|
||||
}
|
||||
if (_sessionClearInProgress)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
|
|
@ -1508,6 +1520,14 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
if (!deferredKnown)
|
||||
return false;
|
||||
|
||||
if (isLocalPlayer
|
||||
&& disposition is not PositionTimestampDisposition.Rejected)
|
||||
{
|
||||
Physics.ObserveLocalWorldFrame(
|
||||
update.Position.LandblockId,
|
||||
timestamps.TeleportAdvanced);
|
||||
}
|
||||
|
||||
if (disposition is PositionTimestampDisposition.Rejected
|
||||
&& !timestampMutation)
|
||||
{
|
||||
|
|
@ -1556,6 +1576,14 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
return known;
|
||||
}
|
||||
|
||||
if (isLocalPlayer
|
||||
&& disposition is not PositionTimestampDisposition.Rejected)
|
||||
{
|
||||
Physics.ObserveLocalWorldFrame(
|
||||
update.Position.LandblockId,
|
||||
timestamps.TeleportAdvanced);
|
||||
}
|
||||
|
||||
bool acceptedPosition =
|
||||
disposition is not PositionTimestampDisposition.Rejected;
|
||||
if (disposition is PositionTimestampDisposition.Apply)
|
||||
|
|
|
|||
|
|
@ -346,7 +346,8 @@ internal sealed class RuntimeRemoteFirstEntryState
|
|||
lease.Route.SetPositionFlags,
|
||||
collisionSource,
|
||||
gameTime,
|
||||
out RuntimeSetPositionCommand command);
|
||||
out RuntimeSetPositionCommand command,
|
||||
resolveWorldOffsetFromRuntimeFrame: true);
|
||||
if (moverStatus
|
||||
== RuntimeSetPositionMoverPreparationStatus.RetrySetupUnavailable)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue