fix(runtime/core): Slice 5.3 review corrections — retirement/transit close, per-unit pricing, guarded auto-close dispatch
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
The adversarial review's three blocking findings, each fixed at root: 1. A vendor session now CLOSES when its entity retires (despawn, death, ObjectDelete) and at teleport BEGIN (HasPendingTeleportStart || IsTeleportActive at the existing per-frame seam — both hosts funnel through RuntimeWorldTransitState.TryQueueTeleportStart, which flips the pending flag strictly before activation). The previous permissive early-return stranded the session forever: panel pinned to a stale guid, ActiveVendorId swallowing Use for the rest of the session. 2. VendorShopItem carries the desc's stack size, and VendorPricing.PerUnitValue ports retail's stack-total division (VendorProfile::VendorSellPrice 0x005D1B00: <= 0 guard, integer division) — a stack of 50 arrows now prices per arrow, not at 50x. 3. VendorState.Close() guards its observer fanout with the dispatcher's catch-and-log semantics — a throwing panel listener can no longer propagate into the unprotected per-frame path. Register honesty rides along: the 0.6 m UseRadius fallback was acdream's invention (ACE's CheckClose has no fallback; retail passes the raw authored radius) — removed, the watcher now uses the raw radius and AP-160's citations are corrected and extended with the accepted-position-snapshot cadence; AD-72 files VendorPricing's double-vs-x87-extended narrowing (AD-33's class, bounded by the ±0.1 margin). Nine tests added. Clean-room complete solution: 11,311 passed / 4 skipped / 0 failed. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9796d71522
commit
609a2dfda0
9 changed files with 369 additions and 23 deletions
|
|
@ -120,6 +120,26 @@ public sealed class VendorStateTests
|
|||
Assert.Equal(0u, change.VendorId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Close_ThrowingObserver_DoesNotPropagateAndStillClosesTheSession()
|
||||
{
|
||||
// Slice 5.3 review fix 3: unlike Reset(), Close() must never
|
||||
// rethrow — its production caller (RuntimeVendorRangeQuery.
|
||||
// EnforceRange) runs inside an unprotected per-frame callback.
|
||||
var state = new VendorState();
|
||||
state.Apply(0x40000007u, default, Array.Empty<VendorShopItem>());
|
||||
|
||||
bool secondObserverRan = false;
|
||||
state.Changed += _ => throw new InvalidOperationException("boom");
|
||||
state.Changed += _ => secondObserverRan = true;
|
||||
|
||||
Exception? thrown = Record.Exception(() => { state.Close(); });
|
||||
|
||||
Assert.Null(thrown);
|
||||
Assert.True(secondObserverRan);
|
||||
Assert.Equal(0u, state.VendorId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Reset_RetryRepublishesAndOneObserverCannotStarveAnother()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue