refactor(app): key live projections by runtime identity
Move materialized live-object sidecars and presentation worksets to exact RuntimeEntityKey ownership. Runtime remains the only GUID/incarnation/local-ID authority while hydration, animation, effects, lights, equipped children, renderer resources, visibility, liveness, and teardown resolve exact projection identities. Preserve synchronous callbacks, local-ID allocation order, and current rendering behavior.
This commit is contained in:
parent
e18df84437
commit
420e5eea70
73 changed files with 2939 additions and 1715 deletions
|
|
@ -65,11 +65,6 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
private EntityPhysicsHost? _playerHost => _playerHostSource.Host;
|
||||
private uint _playerServerGuid => _playerIdentity.ServerGuid;
|
||||
private double _physicsScriptGameTime => _gameTime.CurrentScriptTime;
|
||||
private IReadOnlyDictionary<uint, WorldEntity> _entitiesByServerGuid =>
|
||||
_liveEntities.MaterializedWorldEntities;
|
||||
private IReadOnlyDictionary<uint, WorldEntity> _visibleEntitiesByServerGuid =>
|
||||
_liveEntities.WorldEntities;
|
||||
|
||||
internal uint? LastLivePlayerLandblockId =>
|
||||
_authorityGate.LastLivePlayerLandblockId;
|
||||
|
||||
|
|
@ -262,7 +257,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
ulong acceptedMovementVelocityAuthorityVersion =
|
||||
accepted.VelocityAuthorityVersion;
|
||||
|
||||
if (!_entitiesByServerGuid.TryGetValue(update.Guid, out var entity)) return;
|
||||
if (!_liveEntities.TryGetWorldEntity(update.Guid, out var entity)) return;
|
||||
if (!_animatedEntities.TryGetValue(entity.Id, out var ae))
|
||||
{
|
||||
DispatchRemoteInboundMotion(
|
||||
|
|
@ -566,8 +561,14 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
// window from this transition. Without this, the entity
|
||||
// starts its run animation and is instantly interrupted.
|
||||
var refreshedTime = System.DateTime.UtcNow;
|
||||
if (_remoteMovementObservations.TryGetValue(update.Guid, out var prev))
|
||||
_remoteMovementObservations[update.Guid] = (prev.Pos, refreshedTime);
|
||||
if (acceptedMotionRecord.ProjectionKey is { } motionKey
|
||||
&& _remoteMovementObservations.TryGetValue(
|
||||
motionKey,
|
||||
out var prev))
|
||||
{
|
||||
_remoteMovementObservations[motionKey] =
|
||||
(prev.Pos, refreshedTime);
|
||||
}
|
||||
if (_remoteDeadReckon.TryGetValue(update.Guid, out var dr))
|
||||
dr.LastServerPosTime = (refreshedTime - System.DateTime.UnixEpoch).TotalSeconds;
|
||||
}
|
||||
|
|
@ -817,7 +818,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
ulong acceptedVectorAuthorityVersion,
|
||||
ulong acceptedVectorVelocityAuthorityVersion)
|
||||
{
|
||||
if (!_entitiesByServerGuid.ContainsKey(update.Guid)) return;
|
||||
if (!_liveEntities.ContainsWorldEntity(update.Guid)) return;
|
||||
|
||||
if (update.Guid == _playerServerGuid) return; // local jump uses our own physics
|
||||
if (!_remoteDeadReckon.TryGetValue(update.Guid, out var rm)) return;
|
||||
|
|
@ -863,7 +864,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
// state-derived velocity write (adaptation note: retail's
|
||||
// equivalence comes from the per-tick transition-sweep order —
|
||||
// R6 scope).
|
||||
if (_entitiesByServerGuid.TryGetValue(update.Guid, out var ent)
|
||||
if (_liveEntities.TryGetWorldEntity(update.Guid, out var ent)
|
||||
&& _animatedEntities.TryGetValue(ent.Id, out var ae)
|
||||
&& ae.Sequencer is not null)
|
||||
{
|
||||
|
|
@ -940,12 +941,12 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
if (parsed.Guid == _playerServerGuid)
|
||||
_playerController?.ApplyPhysicsState(record.FinalPhysicsState);
|
||||
|
||||
if (!_entitiesByServerGuid.TryGetValue(parsed.Guid, out var entity)) return;
|
||||
if (!_liveEntities.TryGetWorldEntity(parsed.Guid, out var entity)) return;
|
||||
|
||||
// L.2g slice 1c (2026-05-13): the server addresses entities by
|
||||
// ServerGuid (parsed.Guid, e.g. 0x7A9B4015), but
|
||||
// ShadowObjectRegistry's cell index is keyed by local entity.Id
|
||||
// (e.g. 0x000F4245). Translate via _entitiesByServerGuid before
|
||||
// (e.g. 0x000F4245). Translate through the canonical Runtime directory before
|
||||
// mutating the registry — otherwise the lookup misses and the
|
||||
// state flip silently no-ops, leaving doors blocked even though
|
||||
// ACE flipped the ETHEREAL bit.
|
||||
|
|
@ -1035,7 +1036,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
_playerController)))
|
||||
return;
|
||||
|
||||
if (!_entitiesByServerGuid.ContainsKey(update.Guid))
|
||||
if (!_liveEntities.ContainsWorldEntity(update.Guid))
|
||||
{
|
||||
if (!IsCurrentPositionOwner())
|
||||
return;
|
||||
|
|
@ -1068,7 +1069,7 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
}
|
||||
}
|
||||
|
||||
if (!_entitiesByServerGuid.TryGetValue(update.Guid, out var entity)) return;
|
||||
if (!_liveEntities.TryGetWorldEntity(update.Guid, out var entity)) return;
|
||||
if (!IsCurrentPositionOwner(entity))
|
||||
return;
|
||||
_entityEffects?.MarkLiveOwnerPoseDirty(update.Guid);
|
||||
|
|
@ -1223,16 +1224,20 @@ internal sealed class LiveEntityNetworkUpdateController
|
|||
if (update.Guid != _playerServerGuid)
|
||||
{
|
||||
var now = System.DateTime.UtcNow;
|
||||
if (_remoteMovementObservations.TryGetValue(update.Guid, out var prev))
|
||||
RuntimeEntityKey positionKey = positionRecord.ProjectionKey
|
||||
?? throw new InvalidOperationException(
|
||||
$"Position owner 0x{update.Guid:X8}/" +
|
||||
$"{positionRecord.Generation} has no exact projection key.");
|
||||
if (_remoteMovementObservations.TryGetValue(positionKey, out var prev))
|
||||
{
|
||||
float moveDist = System.Numerics.Vector3.Distance(prev.Pos, worldPos);
|
||||
if (moveDist > 0.05f)
|
||||
_remoteMovementObservations[update.Guid] = (worldPos, now);
|
||||
_remoteMovementObservations[positionKey] = (worldPos, now);
|
||||
// else: leave old entry so "Time" = last real movement time
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteMovementObservations[update.Guid] = (worldPos, now);
|
||||
_remoteMovementObservations[positionKey] = (worldPos, now);
|
||||
}
|
||||
|
||||
// Retail-faithful hard-snap on UpdatePosition.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue