refactor(world): extract live entity hydration
This commit is contained in:
parent
27dcd0ecb7
commit
d10c5f2d54
17 changed files with 4310 additions and 1269 deletions
|
|
@ -258,7 +258,32 @@ public sealed class LiveEntityRecord
|
|||
internal ulong VectorAuthorityVersion { get; private set; }
|
||||
internal ulong VelocityAuthorityVersion { get; private set; }
|
||||
internal ulong MovementAuthorityVersion { get; private set; }
|
||||
/// <summary>
|
||||
/// Advances for every accepted CreateObject affecting this incarnation,
|
||||
/// including a fresher same-INSTANCE_TS retransmit. App integration uses
|
||||
/// it to distinguish two transactions that intentionally share identity.
|
||||
/// </summary>
|
||||
internal ulong CreateIntegrationVersion { get; private set; } = 1UL;
|
||||
public bool WorldSpawnPublished { get; internal set; }
|
||||
/// <summary>
|
||||
/// True only after the incarnation's projection, collision/animation
|
||||
/// components, effect owner, state presentation, and pending-effect replay
|
||||
/// have crossed the initial ready barrier. A non-null
|
||||
/// <see cref="WorldEntity"/> alone is not sufficient: failures after
|
||||
/// resource registration retain the same projection for exact retry.
|
||||
/// </summary>
|
||||
public bool InitialHydrationCompleted { get; internal set; }
|
||||
/// <summary>
|
||||
/// A fresher same-incarnation CreateObject interrupted projection after
|
||||
/// logical ownership had already been established. The retained entity
|
||||
/// must replay the newest canonical appearance/current snapshot/animation
|
||||
/// before ordinary rebucketing can resume. This obligation deliberately
|
||||
/// survives a failed recovery attempt.
|
||||
/// </summary>
|
||||
internal bool CreateProjectionSynchronizationPending { get; set; }
|
||||
internal bool ProjectionHydrationInProgress { get; set; }
|
||||
internal ulong ProjectionHydrationCreateVersion { get; set; }
|
||||
internal bool ProjectionHydrationRetryRequested { get; set; }
|
||||
public LiveEntityProjectionKind ProjectionKind { get; internal set; }
|
||||
internal bool RuntimeComponentsTeardownCompleted { get; set; }
|
||||
internal LiveEntityTeardownPlan? RuntimeComponentTeardownPlan { get; set; }
|
||||
|
|
@ -320,6 +345,7 @@ public sealed class LiveEntityRecord
|
|||
VectorAuthorityVersion++;
|
||||
VelocityAuthorityVersion++;
|
||||
MovementAuthorityVersion++;
|
||||
CreateIntegrationVersion++;
|
||||
}
|
||||
|
||||
internal void SetChildNoDraw(bool noDraw)
|
||||
|
|
@ -2031,6 +2057,111 @@ public sealed class LiveEntityRuntime
|
|||
return true;
|
||||
}
|
||||
|
||||
internal bool TryMarkInitialHydrationCompleted(
|
||||
LiveEntityRecord expectedRecord,
|
||||
ulong expectedCreateIntegrationVersion)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(expectedRecord);
|
||||
if (!IsCurrentRecord(expectedRecord)
|
||||
|| expectedRecord.CreateIntegrationVersion != expectedCreateIntegrationVersion
|
||||
|| expectedRecord.WorldEntity is null
|
||||
|| !expectedRecord.ResourcesRegistered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
expectedRecord.InitialHydrationCompleted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool TryMarkCreateProjectionSynchronizationPending(
|
||||
LiveEntityRecord expectedRecord,
|
||||
ulong expectedCreateIntegrationVersion)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(expectedRecord);
|
||||
if (!IsCurrentCreateIntegration(
|
||||
expectedRecord,
|
||||
expectedCreateIntegrationVersion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
expectedRecord.CreateProjectionSynchronizationPending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool TryCompleteCreateProjectionSynchronization(
|
||||
LiveEntityRecord expectedRecord,
|
||||
ulong expectedCreateIntegrationVersion)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(expectedRecord);
|
||||
if (!IsCurrentCreateIntegration(
|
||||
expectedRecord,
|
||||
expectedCreateIntegrationVersion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
expectedRecord.CreateProjectionSynchronizationPending = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool TryBeginProjectionHydration(
|
||||
LiveEntityRecord expectedRecord,
|
||||
ulong? expectedCreateIntegrationVersion)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(expectedRecord);
|
||||
if (!IsCurrentRecord(expectedRecord)
|
||||
|| (expectedCreateIntegrationVersion is { } expected
|
||||
&& expectedRecord.CreateIntegrationVersion != expected))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expectedRecord.ProjectionHydrationInProgress)
|
||||
{
|
||||
if (expectedRecord.CreateIntegrationVersion
|
||||
!= expectedRecord.ProjectionHydrationCreateVersion)
|
||||
{
|
||||
expectedRecord.ProjectionHydrationRetryRequested = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
expectedRecord.ProjectionHydrationInProgress = true;
|
||||
expectedRecord.ProjectionHydrationCreateVersion =
|
||||
expectedRecord.CreateIntegrationVersion;
|
||||
expectedRecord.ProjectionHydrationRetryRequested = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool EndProjectionHydration(LiveEntityRecord expectedRecord)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(expectedRecord);
|
||||
bool retry = IsCurrentRecord(expectedRecord)
|
||||
&& (expectedRecord.ProjectionHydrationRetryRequested
|
||||
|| expectedRecord.CreateIntegrationVersion
|
||||
!= expectedRecord.ProjectionHydrationCreateVersion);
|
||||
if (retry)
|
||||
{
|
||||
// Persist the exact replay obligation at the point version drift
|
||||
// is observed. The stale projection body may be unwinding through
|
||||
// an exception and therefore never reach the controller's next
|
||||
// retry-loop iteration.
|
||||
expectedRecord.CreateProjectionSynchronizationPending = true;
|
||||
}
|
||||
expectedRecord.ProjectionHydrationInProgress = false;
|
||||
expectedRecord.ProjectionHydrationCreateVersion = 0UL;
|
||||
expectedRecord.ProjectionHydrationRetryRequested = false;
|
||||
return retry;
|
||||
}
|
||||
|
||||
internal bool IsCurrentCreateIntegration(
|
||||
LiveEntityRecord expectedRecord,
|
||||
ulong expectedCreateIntegrationVersion) =>
|
||||
IsCurrentRecord(expectedRecord)
|
||||
&& expectedRecord.CreateIntegrationVersion == expectedCreateIntegrationVersion;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (_isClearing || _isRegisteringResources)
|
||||
|
|
@ -2586,6 +2717,11 @@ public sealed class LiveEntityRuntime
|
|||
record.IsSpatiallyProjected = false;
|
||||
record.IsSpatiallyVisible = false;
|
||||
record.WorldSpawnPublished = false;
|
||||
record.InitialHydrationCompleted = false;
|
||||
record.CreateProjectionSynchronizationPending = false;
|
||||
record.ProjectionHydrationInProgress = false;
|
||||
record.ProjectionHydrationCreateVersion = 0UL;
|
||||
record.ProjectionHydrationRetryRequested = false;
|
||||
record.WorldEntity = null;
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue