refactor(streaming): compose landblock presentation transaction
Own render, physics, DAT-static presentation, and retained static-resource rebinds behind retryable receipts so a failed publication resumes its exact unfinished suffix without replaying retail create-time defaults. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
e1110f7e54
commit
ea0da8c8ae
15 changed files with 1744 additions and 89 deletions
|
|
@ -41,6 +41,9 @@ public sealed class LandblockPresentationPipeline
|
|||
public required uint LandblockId;
|
||||
public LandblockStreamTier Tier;
|
||||
public bool PresentationCommitted;
|
||||
public LandblockRenderPublication? RenderPublication;
|
||||
public LandblockPhysicsPublication? PhysicsPublication;
|
||||
public LandblockStaticPresentationPublication? StaticPublication;
|
||||
public bool SpatialCommitted;
|
||||
public GpuLandblockSpatialPublication? SpatialPublication;
|
||||
public bool SpatialPresentationCommitted;
|
||||
|
|
@ -48,7 +51,11 @@ public sealed class LandblockPresentationPipeline
|
|||
public bool LiveRecoveryCommitted;
|
||||
}
|
||||
|
||||
private readonly Action<LandblockBuild, LandblockMeshData> _publishBeforeSpatialCommit;
|
||||
private readonly Action<LandblockBuild, LandblockMeshData>?
|
||||
_publishBeforeSpatialCommit;
|
||||
private readonly LandblockRenderPublisher? _renderPublisher;
|
||||
private readonly LandblockPhysicsPublisher? _physicsPublisher;
|
||||
private readonly LandblockStaticPresentationPublisher? _staticPublisher;
|
||||
private readonly GpuWorldState _state;
|
||||
private readonly Action<uint>? _onLandblockLoaded;
|
||||
private readonly Action<EnvCellLandblockBuild>? _ensureEnvCellMeshes;
|
||||
|
|
@ -79,6 +86,37 @@ public sealed class LandblockPresentationPipeline
|
|||
demoteNearLayer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Production constructor. The pipeline retains each concrete owner
|
||||
/// receipt before mutation and resumes only the unfinished exact stage
|
||||
/// after a failure.
|
||||
/// </summary>
|
||||
public LandblockPresentationPipeline(
|
||||
LandblockRenderPublisher renderPublisher,
|
||||
LandblockPhysicsPublisher physicsPublisher,
|
||||
LandblockStaticPresentationPublisher staticPublisher,
|
||||
GpuWorldState state,
|
||||
Action<uint>? onLandblockLoaded = null,
|
||||
Action<EnvCellLandblockBuild>? ensureEnvCellMeshes = null,
|
||||
LandblockRetirementCoordinator? retirementCoordinator = null)
|
||||
{
|
||||
_renderPublisher = renderPublisher
|
||||
?? throw new ArgumentNullException(nameof(renderPublisher));
|
||||
_physicsPublisher = physicsPublisher
|
||||
?? throw new ArgumentNullException(nameof(physicsPublisher));
|
||||
_staticPublisher = staticPublisher
|
||||
?? throw new ArgumentNullException(nameof(staticPublisher));
|
||||
_state = state ?? throw new ArgumentNullException(nameof(state));
|
||||
_onLandblockLoaded = onLandblockLoaded;
|
||||
_ensureEnvCellMeshes = ensureEnvCellMeshes;
|
||||
// Until Slice 5F internalizes concrete retirement ownership, a
|
||||
// concrete publication pipeline must share the production coordinator.
|
||||
// A legacy no-op retirement suffix would detach spatial state while
|
||||
// leaking the concrete render/physics/static owners.
|
||||
_retirements = retirementCoordinator
|
||||
?? throw new ArgumentNullException(nameof(retirementCoordinator));
|
||||
}
|
||||
|
||||
public int PendingRetirementCount => _retirements.PendingCount;
|
||||
public int PendingPublicationCount => _publications.Count;
|
||||
|
||||
|
|
@ -219,22 +257,60 @@ public sealed class LandblockPresentationPipeline
|
|||
{
|
||||
if (!transaction.PresentationCommitted)
|
||||
{
|
||||
try
|
||||
if (_renderPublisher is not null
|
||||
&& _physicsPublisher is not null
|
||||
&& _staticPublisher is not null)
|
||||
{
|
||||
_publishBeforeSpatialCommit(transaction.Build, transaction.MeshData);
|
||||
transaction.RenderPublication ??=
|
||||
_renderPublisher.PreparePublication(
|
||||
transaction.Build,
|
||||
transaction.MeshData);
|
||||
transaction.PhysicsPublication ??=
|
||||
_physicsPublisher.PreparePublication(
|
||||
transaction.RenderPublication);
|
||||
transaction.StaticPublication ??=
|
||||
_staticPublisher.PreparePublication(
|
||||
transaction.PhysicsPublication);
|
||||
|
||||
// Prepare every immutable receipt before the first external
|
||||
// mutation. Cross-owner identity/data errors therefore block
|
||||
// the publication without leaving a committed prefix.
|
||||
_renderPublisher.BeginPublication(transaction.RenderPublication);
|
||||
_physicsPublisher.BeginPublication(transaction.PhysicsPublication);
|
||||
|
||||
// Retail establishes the building/visible-cell suffix before
|
||||
// each static object publishes lights, collision, and scripts.
|
||||
_renderPublisher.CompletePublication(
|
||||
transaction.RenderPublication);
|
||||
|
||||
_staticPublisher.BeginPublication(transaction.StaticPublication);
|
||||
_physicsPublisher.CompletePublication(
|
||||
transaction.PhysicsPublication,
|
||||
entity => _staticPublisher.PrepareEntityBeforeCollision(
|
||||
transaction.StaticPublication,
|
||||
entity));
|
||||
_staticPublisher.CompletePublication(
|
||||
transaction.StaticPublication);
|
||||
}
|
||||
catch (Exception error)
|
||||
else
|
||||
{
|
||||
// The legacy GameWindow callback still spans several concrete
|
||||
// owners and cannot report a committed prefix. Until Slice-5
|
||||
// checkpoints C-E replace it with individually ledgered
|
||||
// publishers, its production wrapper conservatively reports a
|
||||
// committed mutation. Test/compatibility callbacks retain the
|
||||
// established strong-exception contract unless they explicitly
|
||||
// report otherwise.
|
||||
if (error is StreamingMutationException { MutationCommitted: true })
|
||||
_publications.Remove(result);
|
||||
throw;
|
||||
try
|
||||
{
|
||||
(_publishBeforeSpatialCommit
|
||||
?? throw new InvalidOperationException(
|
||||
"The presentation pipeline has no publication owners."))(
|
||||
transaction.Build,
|
||||
transaction.MeshData);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
// Compatibility callbacks cannot report an exact retained
|
||||
// receipt. Preserve the established fail-fast rule only
|
||||
// for callbacks that explicitly report committed mutation.
|
||||
if (error is StreamingMutationException { MutationCommitted: true })
|
||||
_publications.Remove(result);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
transaction.PresentationCommitted = true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue