feat(physics): C4 route 4b-2 — remote far snap through the canonical placement
Flips the SetPositionSimple classification (contact, PlayerDistance >= 96 m) for remotes onto 4b-1's drive controller and deletes both legacy far blocks, both duplicated 96f/4f constant pairs, and both `?? Vector3.Zero` fabrications. The 4 m constant now exists exactly once. Teleport and cell-less stay legacy for 4b-3. Retail: MoveOrTeleport @0x00516330's far branch runs StopInterpolating @0x005163CB before SetPositionSimple @0x005163D9 and returns 1 @0x005163E8 regardless — the SetPositionError is discarded — so HandleReceivedPosition arms ConstrainTo @0x00454272 post-move on commit AND on failure. The x87 parity decode at @0x00516393-@0x0051639E puts exactly 96.0 on the far branch. SetPositionSimple @0x005162B0 builds flags 0x1012 at @0x005162C4. Non-commit outcomes still advance the body, because retail's SetPositionInternal @0x00515BD0 commits the destination via store_position @0x00515CE2 when no cell resolves. The partition is by STAGE, not heuristic, enforced by an exhaustive switch: Refused/Contention/NotApplicable/RejectedPreparation store (the placement never executed); Committed/Deferred/RejectedByPlacement do not (the engine ran and refused, matching retail's non-storing returns @0x00515CB2 and @0x00515CD5). Without this a refused far snap froze the remote with an emptied queue. Also fixes a shipped defect this route made live: ParkDeferred's quiescence parks withdrew the entity (InWorld=false, clock suspended, residency removed) and were never restorable, while Forget(restoreCancelledPark: true) runs for every accepted Position on every entity. The restorable decision now lives inside ParkDeferred AFTER SnapToCell, reading body.CellPosition.ObjCellId — the value RestoreParkWithdrawal actually restores at — against every live quiescence rather than one minimum-OperationId token. The three pre-snap fields are hoisted into locals because SnapToCell ends with InWorld = true. ParkCollisionResidents passes restorableOnCancel: false explicitly; the plain unplaceable park is provably unchanged. RestoreParkWithdrawal re-tests the prefix at restore time so a retained route-2 park cannot re-admit into a prefix that began quiescing during the park. CanAttemptDestination is retained as an OPTIMISATION only, with the two Core predicates it cannot reproduce written down at the pre-flight, plus the two properties that depend on it staying there. Four fix rounds and eight Opus reviews. The slice was fully green at 10,990, 10,997 and 11,004 while containing real defects — a frozen remote pinned as correct by its own test, a fallback that over-wrote on the exact retail paths that decline to store, and a park guard incomplete on two independent axes. Register: AP-137 (leftover classifications take AP-87's catch-up; states the cell-less enqueue-vs-place delta deferred to 4b-3, that RejectedData is applied anyway, and the headless divergence), AP-138 (the refusable far placement), AP-136 narrowed to match the relocation. #309's acceptance steps rewritten — step 5 previously asserted a recovery the code does not perform — and gated on a new ACDREAM_PROBE_PARK=1 signal so the check cannot pass while broken. Suite 11,009 passed / 4 skipped / 0 failed against a measured 10,968 baseline. The 10,973 figure recorded earlier was wrong and is corrected here. Connected gate outstanding: the two-client far-snap walk and #309. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1b631f127d
commit
7f1c1f5aa6
24 changed files with 5234 additions and 375 deletions
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using AcDream.Content;
|
||||
|
|
@ -1346,6 +1346,14 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
{
|
||||
EnsureNotDisposed();
|
||||
ArgumentNullException.ThrowIfNull(record);
|
||||
// B2 dependency (C4 route 4b-2): the `_operations.ContainsKey`
|
||||
// refusal is what makes an INHERITED park impossible for any
|
||||
// operation begun here, which is in turn what lets
|
||||
// RuntimeRemotePlacementDriveController document a pre-engine
|
||||
// Rejected as unreachable on its far-snap path (the
|
||||
// WakeableLostCell-only `with` rewrite in
|
||||
// SubmitPreparedPlacementCore cannot apply). Loosening it to admit a
|
||||
// second concurrent operation invalidates that argument.
|
||||
if (record.Key is not { } key
|
||||
|| _operations.ContainsKey(key)
|
||||
|| HasRetainedCompletion(key))
|
||||
|
|
@ -1377,6 +1385,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
|| operation.Stage is not RuntimeEntityPlacementStage
|
||||
.AwaitingPreparation
|
||||
|| !ReferenceEquals(operation.Record, record)
|
||||
// B2 dependency (C4 route 4b-2): this `is not null` is what makes
|
||||
// DormantLocalActivation and "the record has a body" mutually
|
||||
// exclusive, which is the step
|
||||
// RuntimeRemotePlacementDriveController's pre-engine-Rejected
|
||||
// argument uses to dismiss the AwaitingCell stage divergence
|
||||
// between PrepareMover and SubmitPreparedPlacementCore.
|
||||
|| record.PhysicsBody is not null
|
||||
|| !IsCurrent(operation)
|
||||
|| body.InWorld
|
||||
|
|
@ -1560,6 +1574,15 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
command = default;
|
||||
// Round 3 audit: safe - fresh lookup + Token check earlier in this
|
||||
// SAME guard clause precede IsCurrent, nothing reentrant in between.
|
||||
//
|
||||
// B2 dependency (C4 route 4b-2): this guard clause SHADOWS
|
||||
// SubmitPreparedPlacementCore's entry validation one call later, and
|
||||
// RuntimeRemotePlacementDriveController's far-snap default arm
|
||||
// documents a pre-engine `Rejected` as unreachable BECAUSE of that
|
||||
// shadowing - every term dropped from here re-surfaces there as a
|
||||
// non-storing Rejected instead of a storing RejectedAuthority. The
|
||||
// one term it deliberately does NOT shadow is the null-body test;
|
||||
// that caller's own entry check covers it, and says so.
|
||||
if (!token.IsValid
|
||||
|| !_operations.TryGetValue(token.Entity, out Operation? operation)
|
||||
|| operation.Token != token
|
||||
|
|
@ -2977,7 +3000,12 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
collisionGenerationOverride:
|
||||
quiescence!.Token.CollisionGeneration,
|
||||
collisionPrefixOverride:
|
||||
quiescence.Token.LandblockPrefix);
|
||||
quiescence.Token.LandblockPrefix,
|
||||
// A quiescence park is a momentarily-unavailable destination,
|
||||
// not a world going away, so it is eligible for the rollback.
|
||||
// ParkDeferred is what decides whether the cell it would
|
||||
// restore into is itself quiescing.
|
||||
restorableOnCancel: true);
|
||||
}
|
||||
|
||||
PhysicsSetPositionResult result;
|
||||
|
|
@ -3028,7 +3056,11 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
collisionGenerationOverride:
|
||||
queriedQuiescence!.Token.CollisionGeneration,
|
||||
collisionPrefixOverride:
|
||||
queriedQuiescence.Token.LandblockPrefix);
|
||||
queriedQuiescence.Token.LandblockPrefix,
|
||||
// Same reason as the pre-sweep park above, plus the swept
|
||||
// footprint: ResultTouchesPrefix scans every QueriedCellIds
|
||||
// entry, and that set spans NEIGHBOUR landblocks.
|
||||
restorableOnCancel: true);
|
||||
}
|
||||
operation.Result = result;
|
||||
if (!result.IsSuccessful)
|
||||
|
|
@ -3048,9 +3080,9 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
_preparedMovers[operation.Key] = canonicalRequest;
|
||||
|
||||
if (result.IsDeferred)
|
||||
// The one restorable park: the destination is not placeable right
|
||||
// now. Every other ParkDeferred caller is a quiescence/retirement
|
||||
// withdrawal - see ParkDeferred's restorableOnCancel doc.
|
||||
// The plain restorable park: the destination is not placeable
|
||||
// right now. The only NON-restorable caller is the retirement
|
||||
// park - see ParkDeferred's restorableOnCancel doc.
|
||||
return ParkDeferred(operation, result, restorableOnCancel: true);
|
||||
|
||||
if (!CommitCanonical(operation, result))
|
||||
|
|
@ -3418,6 +3450,13 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
/// cancelled park cannot leave the entity invisible and intangible with
|
||||
/// nothing able to wake it.
|
||||
///
|
||||
/// <para>Residency specifically is re-tested against the live quiescence
|
||||
/// map HERE as well as at park time, because this runs on a later packet
|
||||
/// for a retained park - see the inline comment for the window. The
|
||||
/// <c>InWorld</c>/transient/clock half is restored unconditionally: it is
|
||||
/// per-entity simulation state, not a claim on any landblock's collision
|
||||
/// generation, so it cannot block a retirement.</para>
|
||||
///
|
||||
/// <para><b>The committed pose is deliberately left alone.</b>
|
||||
/// <see cref="ParkDeferred"/> snaps the body to the destination before
|
||||
/// withdrawing, which is precisely retail's lost-cell behaviour:
|
||||
|
|
@ -3476,13 +3515,39 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
}
|
||||
if (withdrawal.ClockActive)
|
||||
_entities.ResumeObjectClock(record);
|
||||
if (residentCellId != 0u && record.FullCellId == 0u)
|
||||
// Round 4 (D6): the park-time decision in ParkDeferred is a SNAPSHOT,
|
||||
// and for a RETAINED park it can be stale by the time this runs. The
|
||||
// far snap's park is cancelled synchronously (SubmitAndResolve's
|
||||
// DeferredCell arm), so its window is nanoseconds - but route 2's
|
||||
// park is retained (AwaitingCommitWake) and this restore lands on the
|
||||
// NEXT packet's merge-time Forget, ~150 ms later at ACE's 5-10 Hz.
|
||||
// Streaming opens a quiescence per landblock mutation, so a prefix
|
||||
// that was clean when the park was taken can be quiescing now.
|
||||
// Re-testing here is what makes AP-136's claim - "the rollback never
|
||||
// re-admits a spatial root into a retiring prefix" - exact at the
|
||||
// moment residency is actually written, instead of true only as of
|
||||
// when the park was taken. The `!= 0u` test ahead of it is also the
|
||||
// C3c-F3 sentinel guard ParkDeferred applies: AdjustToOutside zeroes
|
||||
// the cell id on map-edge failure, and prefix 0x00000000 is the
|
||||
// legitimate corner landblock.
|
||||
bool residencyRestored = false;
|
||||
if (residentCellId != 0u
|
||||
&& !IsCollisionPrefixQuiescing(residentCellId)
|
||||
&& record.FullCellId == 0u)
|
||||
{
|
||||
_entities.SetFullCell(
|
||||
record,
|
||||
residentCellId,
|
||||
(residentCellId & 0xFFFF0000u) | 0xFFFFu);
|
||||
_physics.AcknowledgeSpatialProjection(record, spatial: true);
|
||||
residencyRestored = true;
|
||||
}
|
||||
// Issue #309's connected-gate confirmation signal; see the [park]
|
||||
// line's own comment in ParkDeferred.
|
||||
if (PhysicsDiagnostics.ProbeParkEnabled)
|
||||
{
|
||||
Console.WriteLine(FormattableString.Invariant(
|
||||
$"[park-restore] guid=0x{record.ServerGuid:X8} restoreCell=0x{residentCellId:X8} inWorld={withdrawal.InWorld} residency={residencyRestored}"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3687,7 +3752,13 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
collisionGenerationOverride:
|
||||
quiescence?.Token.CollisionGeneration,
|
||||
collisionPrefixOverride:
|
||||
quiescence?.Token.LandblockPrefix);
|
||||
quiescence?.Token.LandblockPrefix,
|
||||
// Stated, not inherited from the parameter default: a
|
||||
// RETIREMENT park withdraws the entity because its own world
|
||||
// is going away, which is the one shape AP-136's reason
|
||||
// covers exactly. Round 3 (m5) - the blanket doc that used to
|
||||
// guard a forgetful caller here is gone.
|
||||
restorableOnCancel: false);
|
||||
if (_pendingProjection.TryGetValue(
|
||||
parked.Projection.Sequence,
|
||||
out RuntimePlacementProjectionSnapshot staged))
|
||||
|
|
@ -4252,20 +4323,97 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
/// 0x00000000: a corner-landblock quiescence override read as "absent",
|
||||
/// so <see cref="Operation.CollisionQuiescenceHeld"/> derived false and
|
||||
/// the parked operation skipped the QuiescenceHeld stage entirely.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// <paramref name="restorableOnCancel"/> opts this park into
|
||||
/// <see cref="Forget"/>'s rollback. It is true for exactly one caller:
|
||||
/// the plain "destination is not placeable right now" park, which is the
|
||||
/// one that strands an entity when a later packet cancels it.
|
||||
///
|
||||
/// <para>It is deliberately FALSE for every quiescence/retirement park.
|
||||
/// Those withdraw the entity precisely because its own landblock prefix
|
||||
/// is being retired or held, so restoring canonical residency there would
|
||||
/// re-admit a spatial root into the prefix that is trying to quiesce and
|
||||
/// block the retirement outright - a streaming stall traded for a
|
||||
/// stranded entity. Those entities are withdrawn because their world is
|
||||
/// going away, not because a destination was momentarily unavailable.</para>
|
||||
/// <para>
|
||||
/// <paramref name="restorableOnCancel"/> is the caller's HALF of the
|
||||
/// opt-in into <see cref="Forget"/>'s rollback: "this park is a
|
||||
/// momentarily-unavailable destination, not a world going away". It is
|
||||
/// true for the plain "destination is not placeable right now" park and
|
||||
/// for <see cref="SubmitPreparedPlacementCore"/>'s two collision-prefix
|
||||
/// QUIESCENCE parks; it is false for a retirement park
|
||||
/// (<see cref="ParkCollisionResidents"/>), which withdraws the entity
|
||||
/// precisely because its own world is being retired.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// The OTHER half is decided here, after <see cref="PhysicsBody.SnapToCell"/>
|
||||
/// has committed the parked pose, and it is the only test AP-136's stated
|
||||
/// reason actually needs: the rollback restores canonical residency at
|
||||
/// <c>body.CellPosition.ObjCellId</c>
|
||||
/// (<see cref="RestoreParkWithdrawal"/>), so it is safe exactly when THAT
|
||||
/// cell's prefix is not itself quiescing
|
||||
/// (<see cref="IsCollisionPrefixQuiescing"/> — the pre-flight's own
|
||||
/// predicate). Deciding it here rather than at the call sites is what
|
||||
/// makes the claim true rather than approximately true, for two
|
||||
/// independent reasons (C4 route 4b-2, round-3 correction A1):
|
||||
/// </para>
|
||||
/// <list type="number">
|
||||
/// <item><description>A blocking-quiescence token is the MINIMUM-
|
||||
/// <c>OperationId</c> match, not the only live one —
|
||||
/// <c>_collisionPrefixQuiescence</c> is a per-prefix dictionary and a
|
||||
/// streaming recentre opens one per landblock mutation. Comparing the
|
||||
/// restore cell against that single token proves nothing about the
|
||||
/// others, so it could answer "safe" for a destination that is itself
|
||||
/// retiring. (Round 4 bounded the reach rather than asserting it. On a
|
||||
/// FIRST submit it is unreachable, and provably so: the pre-engine check
|
||||
/// can match at most the request's own prefix and its
|
||||
/// <c>CurrentCellId</c>, which are the same prefix there, so its token IS
|
||||
/// the restore cell's; and the post-sweep check runs only once the
|
||||
/// pre-engine check has proven the destination prefix is NOT quiescing,
|
||||
/// so its token can never be. What is NOT ruled out is a RETAINED
|
||||
/// operation whose <c>CurrentCellId</c> has since been moved to another
|
||||
/// landblock by a non-Position rebucket — see the arm's own scoping
|
||||
/// below — with concurrent quiescences on both prefixes. That shape is
|
||||
/// unmeasured, and it is exactly the shape the far arm's pre-flight
|
||||
/// refuses on the only route that has one. Testing the live map here
|
||||
/// makes the decision free of the question rather than dependent on
|
||||
/// it.)</description></item>
|
||||
/// <item><description>The restore cell is not the caller's
|
||||
/// <c>result.CellId</c>. <see cref="PhysicsBody.StageDormantCellFrame"/>
|
||||
/// runs <see cref="AcDream.Core.Physics.LandDefs.AdjustToOutside"/> for
|
||||
/// any outdoor cell, whose own contract says the re-derived id may belong
|
||||
/// to a NEIGHBOUR landblock. Only the post-snap value is the value the
|
||||
/// rollback will use. This is the reachable half, and it is pinned by
|
||||
/// <c>QuiescingOwnPrefix_SeamCrossingParkIsRestoredAtTheReDerivedNeighbourCell</c>:
|
||||
/// a wire (cell, position) pair whose position lies past its own named
|
||||
/// block's seam is exactly the pair #107's re-derivation exists to
|
||||
/// distrust, and the entity is stranded without this.</description></item>
|
||||
/// </list>
|
||||
///
|
||||
/// <para>
|
||||
/// AP-136's blanket "no quiescence park is restorable" was over-broad
|
||||
/// because <see cref="TryGetBlockingQuiescence"/> also fires on prefixes a
|
||||
/// placement merely TOUCHES — chiefly any <c>QueriedCellIds</c> entry
|
||||
/// (a NEIGHBOUR the sweep reached across a seam;
|
||||
/// <c>CellTransit.AddOutsideCell</c> has no same-block filter), and the
|
||||
/// request's <c>CurrentCellId</c>.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// <b>What <c>CurrentCellId</c> names, scoped to the submit (round 4,
|
||||
/// D5).</b> On the FIRST submit of an accepted Position it names the
|
||||
/// DESTINATION, not a departed source: both accepted-Position callers
|
||||
/// commit the accepted wire cell to <c>record.FullCellId</c> ahead of the
|
||||
/// drive (route 2 through the merge, the graphical remote path through
|
||||
/// <c>LiveEntityRuntime.RebucketLiveEntity</c>), and this request field is
|
||||
/// read from that same record field. It is NOT invariant for a RETAINED
|
||||
/// operation: both drives re-submit from their own cadence pump with no
|
||||
/// fresh merge in between (<c>SubmitAndResolve</c> re-reads the record as
|
||||
/// it then stands), and <c>RemoteTeleportController</c>'s rollback is a
|
||||
/// shipped writer that rebuckets <c>FullCellId</c> back to the
|
||||
/// PRE-teleport landblock. <c>RuntimeRemotePlacementDriveController</c>'s
|
||||
/// <c>CanAttemptDestination</c> doc states this correctly; treat the arm
|
||||
/// as live, not as dead code.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// In those touched-prefix
|
||||
/// shapes the retiring prefix is not the one residency is restored into,
|
||||
/// so the rollback pins nothing, while leaving the park non-restorable
|
||||
/// stranded the entity (<c>InWorld = false</c>, clock suspended,
|
||||
/// <c>FullCellId = 0</c>) with the only operation able to wake it
|
||||
/// destroyed by its own next accepted Position.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
private RuntimeSetPositionOutcome ParkDeferred(
|
||||
Operation operation,
|
||||
|
|
@ -4276,21 +4424,55 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
bool restorableOnCancel = false)
|
||||
{
|
||||
PhysicsBody body = operation.Body!;
|
||||
// Captured BEFORE the withdrawal below clears it. Only the
|
||||
// WITHDRAWAL is captured, never the pose: the SnapToCell on the next
|
||||
// line deliberately commits the destination pose and that commit
|
||||
// stands, exactly as retail's store_position @0x00515CE2 commits it
|
||||
// on the lost-cell branch and never un-commits it.
|
||||
operation.ParkWithdrawal = new ParkWithdrawal(
|
||||
Captured: restorableOnCancel,
|
||||
InWorld: body.InWorld,
|
||||
TransientState: body.TransientState,
|
||||
ClockActive: operation.Record.ObjectClock.IsActive);
|
||||
// Read BEFORE the withdrawal below clears them - and before the
|
||||
// SnapToCell, which sets InWorld = true itself. Only the WITHDRAWAL
|
||||
// is captured, never the pose: the SnapToCell deliberately commits
|
||||
// the destination pose and that commit stands, exactly as retail's
|
||||
// store_position @0x00515CE2 commits it on the lost-cell branch and
|
||||
// never un-commits it.
|
||||
bool priorInWorld = body.InWorld;
|
||||
TransientStateFlags priorTransientState = body.TransientState;
|
||||
bool priorClockActive = operation.Record.ObjectClock.IsActive;
|
||||
body.Orientation = result.Orientation;
|
||||
body.SnapToCell(
|
||||
result.CellId,
|
||||
result.Position,
|
||||
result.CellLocalPosition);
|
||||
// The restorable decision reads the POST-snap cell, because that is
|
||||
// the cell RestoreParkWithdrawal will restore residency into - see
|
||||
// this method's own doc for why the caller's result.CellId and a
|
||||
// single blocking-quiescence token are both the wrong inputs.
|
||||
//
|
||||
// C3c-F3 sentinel guard (round 4, N1): cell id 0 is
|
||||
// AdjustToOutside's map-edge FAILURE sentinel
|
||||
// (LandDefs.AdjustToOutside's `cellId = 0u; return false` tail), and
|
||||
// prefix 0x00000000 is simultaneously the LEGITIMATE corner landblock
|
||||
// (0,0) - which is exactly why BeginCollisionPrefixQuiescence rejects
|
||||
// landblock id 0 rather than treating it as "absent". So the
|
||||
// quiescence map must never be consulted with the sentinel: a corner
|
||||
// landblock quiescing would otherwise make every map-edge failure
|
||||
// read as "restoring into a retiring prefix". A sentinel cell has no
|
||||
// residency to re-admit anywhere - RestoreParkWithdrawal applies the
|
||||
// same `!= 0u` test before it restores residency at all - so the
|
||||
// decision falls back to the caller's half alone.
|
||||
uint parkedCellId = body.CellPosition.ObjCellId;
|
||||
operation.ParkWithdrawal = new ParkWithdrawal(
|
||||
Captured: restorableOnCancel
|
||||
&& (parkedCellId == 0u
|
||||
|| !IsCollisionPrefixQuiescing(parkedCellId)),
|
||||
InWorld: priorInWorld,
|
||||
TransientState: priorTransientState,
|
||||
ClockActive: priorClockActive);
|
||||
// Issue #309's connected-gate confirmation signal. Off by default;
|
||||
// one line per park, nothing at all for a committing placement.
|
||||
if (PhysicsDiagnostics.ProbeParkEnabled)
|
||||
{
|
||||
string parkCause = collisionPrefixOverride is uint blockedPrefix
|
||||
? FormattableString.Invariant($"quiescence:0x{blockedPrefix:X8}")
|
||||
: "unplaceable";
|
||||
Console.WriteLine(FormattableString.Invariant(
|
||||
$"[park] guid=0x{operation.Record.ServerGuid:X8} cause={parkCause} resultCell=0x{result.CellId:X8} restoreCell=0x{parkedCellId:X8} eligible={restorableOnCancel} captured={operation.ParkWithdrawal.Captured}"));
|
||||
}
|
||||
body.InWorld = false;
|
||||
body.TransientState &= ~TransientStateFlags.Active;
|
||||
if (operation.Record.RemoteMotion is IRuntimeRemotePlacement remote)
|
||||
|
|
@ -5231,6 +5413,17 @@ internal sealed class RuntimeSetPositionState : IDisposable
|
|||
orientation.Y,
|
||||
orientation.Z);
|
||||
|
||||
/// <summary>
|
||||
/// B2 dependency (C4 route 4b-2): all SEVEN version dimensions below are
|
||||
/// load-bearing for <c>RuntimeRemotePlacementDriveController</c>'s
|
||||
/// documented invariant that a PRE-engine <c>Rejected</c> can never reach
|
||||
/// its far-snap default arm — it relies on <see cref="PrepareMover"/>
|
||||
/// catching every authority divergence one call earlier, as
|
||||
/// <c>RejectedAuthority</c> (which STORES), rather than
|
||||
/// <see cref="SubmitPreparedPlacementCore"/> catching it as
|
||||
/// <c>Rejected</c> (which does not). Dropping a dimension here silently
|
||||
/// moves that shape to the non-storing arm.
|
||||
/// </summary>
|
||||
private static bool IsPreparationAuthorityCurrent(
|
||||
Operation operation,
|
||||
in MoverPreparationAuthority authority) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue