feat(runtime): C3c - production placement cutover: both hosts on the residence conductors (routes 1+8)
Campaign P remaining-physics-divergence, placement cutover slice C3c
(docs/plans/2026-08-02-placement-cutover.md). Both production hosts now
register every initial Create through the residence + continuation-
executor + first-entry-conductor machinery (C0-C3b):
- Graphical (route 1): RegisterEntityWithInitialResidence at Create; the
shared RuntimeFirstEntryDriveController pumps both conductors from the
placement-receipt flow; MaterializeProjection and RebucketLiveEntity
are presentation-only while a residence is ACTIVE (ExecutorCompleted is
the presentation-binding receipt); post-residence entities take the
full legacy path including the prepare_to_enter_world clock edges.
PlayerModeController attaches presentation to the Runtime-published
controller; its legacy resolve/step-heights/host-construction path is
deleted; presentation-only rollback (retail has no entry-flow rollback).
- Headless (route 8): OnSpawned registers with residence when a drive
exists; content-less sessions keep the pre-flip direct registration;
SynchronizeLocalPlayer/CreateController/ApplySetupStepHeights deleted;
prepared-collision read failure is a typed AwaitingCollisionSource
retry; far remotes outside the service window complete celless.
- RuntimeLocalPlayerMovementState.Controller setter sealed internal; all
controller mutation flows through the publication lifecycle.
Fix slices landed within this cutover, each dual-gated:
- F1: live movement-stat/server-physics application routed through the
Runtime ownership seam (post-logout ingest crash on the retired
controller eliminated; RuntimeMovementSkillProjection deleted).
- F2: login activation wedge - collision-admission prefix gate factored
out of the seal (reentrant-commit RejectedAuthority), rearm generation
identity corrected, PlayerModeAutoEntry requires the Runtime-published
controller (world reveal can no longer seal unmaterialized).
- F3: landblock-prefix 0-sentinel replaced by explicit absent-id guards;
map-corner landblocks (grid row/col 0) fully legal through admission,
park/rearm/retire, quiescence, and outdoor shadow seeds.
- F5: local-player first-entry ground contact seeded by the shared
SpawnPlacementSettler (moved App->Core) at FinalizeActivation - the
retail first-gravity-frame touch (enter_world 0x00516170 carries no
seed); the legacy unconditional force-seed is overwritten by a real
floor-found contact; airborne spawns stay airborne; outbound contact
bit verified end-to-end. Fixes the standing-cast 'You can't do that
while in the air!' rejections.
- R1 (dual-review round): login constraint leash armed at the committed
placement (HandleReceivedPosition 0x00453FD0 analog); register rows
AD-61 (settle-timing compression now covering the local player) and
AD-42 (repointed off the deleted resolve split) in this commit;
residence-conversion owner API; wire-landblock guards; drive-pending
ledger in IsConverged; route attach/detach latch; executor-drain drift
model documented + source-pinned.
Gates: Runtime 1,003, App 4,039/3 skips, Headless 79, complete solution
10,816/0 failed/4 skips (Release, -m:1); connected lifecycle/reconnect
gate PASS (logs/connected-world-gate-20260802-175401; graceful exits,
world-visible, zero airborne rejections). The nine-stop soak remains red
for the pre-existing 6b28ff99 whole-world collision-clone throughput
regression (attributed with evidence; scheduled as its own slice before
C5). Dual Opus reviews (retail-conformance + adversarial): delta PASS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
78f1eb1896
commit
529e0e9d88
68 changed files with 5977 additions and 831 deletions
|
|
@ -70,7 +70,16 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
|
|||
/// keys - the remote/projectile Create-time body-construction conductor.
|
||||
/// Dormant like its C3a sibling; converges to zero the same way.
|
||||
/// </summary>
|
||||
int RemoteFirstEntryActiveCount = 0)
|
||||
int RemoteFirstEntryActiveCount = 0,
|
||||
/// <summary>
|
||||
/// C3c-R1 review F5: outstanding host first-entry drive entries
|
||||
/// (<c>RuntimeFirstEntryDriveController</c> pending keys, summed over
|
||||
/// every drive registered against this lifetime via
|
||||
/// <see cref="RuntimeEntityObjectLifetime.RegisterFirstEntryDriveOwnership"/>).
|
||||
/// Previously outside every ledger; gated by <see cref="IsConverged"/>
|
||||
/// like the conductor counts it pumps.
|
||||
/// </summary>
|
||||
int FirstEntryDrivePendingCount = 0)
|
||||
{
|
||||
public bool IsConverged =>
|
||||
IsDisposed
|
||||
|
|
@ -94,6 +103,7 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
|
|||
&& PendingCompletionReceiptCount == 0
|
||||
&& LocalPlayerFirstEntryActiveCount == 0
|
||||
&& RemoteFirstEntryActiveCount == 0
|
||||
&& FirstEntryDrivePendingCount == 0
|
||||
&& StreamSubscriberCount == 0
|
||||
&& PlacementStreamSubscriberCount == 0
|
||||
&& PendingDispatchCount == 0
|
||||
|
|
@ -137,6 +147,10 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
{
|
||||
private bool _sessionClearInProgress;
|
||||
private bool _disposed;
|
||||
/// <summary>C3c: see <see cref="BindInitialResidenceBeginNotification"/>.</summary>
|
||||
private Action<RuntimeEntityRecord>? _initialResidenceBegan;
|
||||
/// <summary>C3c-R1 review F5: see <see cref="RegisterFirstEntryDriveOwnership"/>.</summary>
|
||||
private readonly List<Func<int>> _firstEntryDriveOwnership = [];
|
||||
|
||||
public RuntimeEntityObjectLifetime(
|
||||
uint firstLocalEntityId = RuntimeEntityDirectory.FirstLocalEntityId,
|
||||
|
|
@ -437,7 +451,31 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
InitialCreateExecution.LastReplayFailure is not null,
|
||||
InitialCreateExecution.PendingCompletionReceiptCount,
|
||||
LocalPlayerFirstEntry.CaptureOwnership().ActiveCount,
|
||||
RemoteFirstEntry.CaptureOwnership().ActiveCount);
|
||||
RemoteFirstEntry.CaptureOwnership().ActiveCount,
|
||||
CaptureFirstEntryDrivePendingCount());
|
||||
}
|
||||
|
||||
private int CaptureFirstEntryDrivePendingCount()
|
||||
{
|
||||
int total = 0;
|
||||
for (int i = 0; i < _firstEntryDriveOwnership.Count; i++)
|
||||
total = checked(total + _firstEntryDriveOwnership[i]());
|
||||
return total;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C3c-R1 review F5: registers one host first-entry drive controller's
|
||||
/// pending-count provider into this lifetime's ownership snapshot, so
|
||||
/// tracked-but-undriven entries can never sit outside every ledger. The
|
||||
/// drive controller registers itself at construction (it already binds
|
||||
/// <see cref="BindInitialResidenceBeginNotification"/> there); multiple
|
||||
/// registrations sum, mirroring the multicast notification shape.
|
||||
/// </summary>
|
||||
public void RegisterFirstEntryDriveOwnership(Func<int> pendingCount)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(pendingCount);
|
||||
EnsureNotDisposed();
|
||||
_firstEntryDriveOwnership.Add(pendingCount);
|
||||
}
|
||||
|
||||
public void BindEventContext(
|
||||
|
|
@ -451,6 +489,22 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
InitialCreateExecution.BindGeneration(generation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C3c: registers one host callback fired for every FRESH initial-create
|
||||
/// residence begin (never for a same-generation FIFO append). Multicast,
|
||||
/// mirroring <see cref="RuntimeInitialCreateResidenceState.BindRetirementNotification"/>.
|
||||
/// The callback runs synchronously inside the registration transaction —
|
||||
/// subscribers must only record the entity for a later drive pump, never
|
||||
/// call a conductor's Advance re-entrantly from it.
|
||||
/// </summary>
|
||||
public void BindInitialResidenceBeginNotification(
|
||||
Action<RuntimeEntityRecord> began)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(began);
|
||||
EnsureNotDisposed();
|
||||
_initialResidenceBegan += began;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C0-2: forwards to <see cref="RuntimeInitialCreateContinuationExecutor.BindLiveInputs"/>,
|
||||
/// the same fan-out shape <see cref="BindEventContext"/> already uses for
|
||||
|
|
@ -2270,6 +2324,20 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
return InitialCreateResidences.TryGetCurrent(canonical, out lease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C3c-R1 review F7: host seam for a bounded-collision-neighborhood
|
||||
/// host to convert a remote/projectile Create's active residence to the
|
||||
/// celless completion route when its destination landblock will never
|
||||
/// be collision-published (a headless far remote). See
|
||||
/// <see cref="RuntimeInitialCreateResidenceState.TryConvertToCellessRoute"/>.
|
||||
/// </summary>
|
||||
public bool TryConvertInitialResidenceToCellessRoute(
|
||||
RuntimeEntityRecord canonical)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
return InitialCreateResidences.TryConvertToCellessRoute(canonical);
|
||||
}
|
||||
|
||||
internal RuntimeInitialCreateResidenceCompletionStatus
|
||||
CompleteInitialCreateResidence(
|
||||
RuntimeEntityRecord canonical,
|
||||
|
|
@ -2339,7 +2407,19 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|
|||
canonical,
|
||||
accepted,
|
||||
isLocalPlayer);
|
||||
return lease.IsValid;
|
||||
if (!lease.IsValid)
|
||||
return false;
|
||||
// C3c: host drive notification. Fires for EVERY fresh residence
|
||||
// begin through this single choke point — wire-dispatch Creates AND
|
||||
// the executor's deferred-child replays (which register through this
|
||||
// class's own bound delegate, never through a host runtime). The
|
||||
// subscriber must only RECORD the key for a later drive pump — this
|
||||
// fires mid-registration, before Registered publishes, and a
|
||||
// synchronous Advance here would interleave with the enclosing
|
||||
// transaction (and, for a replayed child, with the parent's own
|
||||
// in-flight Execute).
|
||||
_initialResidenceBegan?.Invoke(canonical);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Exception FailInitialResidenceRegistration(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue