test(vfx): harden live missile and effect lifetimes
Add deterministic 96-owner lifecycle and renderer-resource stress gates plus an exact twelve-cycle recall/portal ownership gate. Prove zero retained records, projectiles, spatial buckets, script queues, particle/light owners, shadows, pending effects, and mesh references after churn, GUID reuse, deletion, and session reset. Make logical teardown incarnation-specific and reentrancy-safe with lifetime epochs, atomic resource registration, generation-aware effect/teleport cleanup, projection mutation tokens, and failure-isolated visibility fan-out. Finish canonical spatial transactions before reporting observer failures and never discard superseded cleanup failures. Synchronize architecture, roadmap, milestones, retail research, divergence bookkeeping, and durable memory. All three independent review tracks are clean; Release build and the full 5,454-pass/5-skip suite are green. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
1e98d81448
commit
8d63e5c28a
21 changed files with 2704 additions and 100 deletions
|
|
@ -1076,3 +1076,96 @@ publishes final part poses later in the same frame. PhysicsScript/particle/light
|
|||
ticks therefore observe the projectile's current predicted root. The controller never
|
||||
creates impact effects, collision messages, damage, or deletion; ACE's later
|
||||
packets remain authoritative for every gameplay outcome.
|
||||
|
||||
## Step 9 — deterministic lifecycle-hardening map (2026-07-14)
|
||||
|
||||
Step 9 adds no new AC algorithm and therefore no replacement retail formula.
|
||||
It verifies that the mechanisms above compose without retaining a displaced
|
||||
object incarnation. The acceptance oracle is ownership symmetry:
|
||||
|
||||
```text
|
||||
create 96 live missile/effect owners at a fixed clock and RNG seed
|
||||
queue F754 before CreateObject
|
||||
register one canonical live record/local ID
|
||||
materialize through the ordinary live-entity resource seam
|
||||
bind the projectile to that record's canonical PhysicsBody
|
||||
register its collision shadow, effect profile, pose, emitter, and light
|
||||
|
||||
advance all owners together
|
||||
execute the initial PES hook and retain a future hook in each serial FIFO
|
||||
tick the ordinary ProjectileController path
|
||||
never create a projectile-specific renderer registration or draw pass
|
||||
|
||||
churn spatial residence
|
||||
rebucket half loaded -> pending -> loaded
|
||||
unload/reload that destination landblock
|
||||
retain the exact local ID, body, renderer owner, effect owner, and FIFO
|
||||
pause/resume particle presentation and dynamic lights at projection edges
|
||||
|
||||
churn logical lifetime
|
||||
rapidly delete 32 owners
|
||||
recreate the same server GUIDs with a newer INSTANCE_TS
|
||||
prove the replacement owns new local IDs and no prior-generation resource
|
||||
mix individual deletes with session reset and never-created pending F754
|
||||
|
||||
terminal assertions
|
||||
zero live/materialized records and null body/projectile/effect/world refs
|
||||
zero loaded/pending/rescued live projection references
|
||||
zero render owners and balanced EntitySpawnAdapter mesh refcounts
|
||||
zero active, retained, and suspended collision-shadow registrations
|
||||
zero ready effect profiles and pending F754/F755 packets
|
||||
zero PhysicsScript owner queues, anchors, and delayed CallPES hooks
|
||||
zero particle emitters/particles/bindings/logical IDs/owner/render-pass maps
|
||||
zero effect poses and light controller/sink/manager owner maps
|
||||
|
||||
repeat the recall/portal lifecycle
|
||||
resolve exact action motion 0x10000153 through an in-memory MotionTable
|
||||
drain its animation CallPES through the shared router and serial scheduler
|
||||
apply Hidden, park authoritative placement in an unloaded destination
|
||||
hydrate and collision-seat that same body, then apply UnHide
|
||||
repeat twelve times while retaining one local ID and one logical owner
|
||||
finish with zero placement, presentation, script, particle, pose, and shadow owners
|
||||
```
|
||||
|
||||
The stress design exposed five ownership defects rather than masking them:
|
||||
|
||||
1. `GpuWorldState::RemoveLandblock` can rescue a persistent player projection
|
||||
before the next frame drains it. Rebucket/delete now scrubs an undrained
|
||||
rescue reference, while the session-scoped persistent GUID classification
|
||||
deliberately survives same-GUID generation replacement and clears only at
|
||||
accepted delete/session teardown.
|
||||
2. Spatial visibility callbacks are serialized and can be re-entrant. An old
|
||||
queued GUID edge is now ignored unless it still equals current spatial truth,
|
||||
so deleting/recreating a GUID inside an observer cannot hide or re-register
|
||||
the replacement incarnation. Each rebucket/withdrawal also captures the
|
||||
record reference plus a projection mutation token; an observer that replaces
|
||||
the GUID or reprojects the same record supersedes the outer transaction.
|
||||
3. Logical delete and generation replacement previously tore down spatial and
|
||||
runtime indices by GUID after arbitrary callbacks. Teardown now captures and
|
||||
removes the accepted record before callbacks, removes its exact WorldEntity
|
||||
reference, and clears generation/local-ID owners only when they still belong
|
||||
to that record. A per-GUID mutation epoch prevents an outer CreateObject from
|
||||
resurrecting after a nested delete/reset, while unrelated GUID activity does
|
||||
not cancel it. Its tombstone remains until session clear so nested
|
||||
delete-then-create cannot repeat the outer operation's epoch. A teardown
|
||||
failure is thrown at the runtime boundary even when a nested newer generation
|
||||
supersedes the outer create. Materialization is an atomic boundary: logical mutation from a
|
||||
resource-registration callback is rejected and rolled back, and a replacement
|
||||
registered during old teardown cannot materialize until that teardown ends.
|
||||
4. Session Clear previously snapshotted records while allowing callbacks to
|
||||
register owners outside the snapshot. Registration is now rejected during
|
||||
terminal clear, preventing untracked renderer/script resources; snapshot
|
||||
entries already deleted by an earlier callback are skipped rather than torn
|
||||
down twice.
|
||||
5. Visibility dispatch previously stopped at the first throwing observer. Both
|
||||
spatial and live-presentation fan-outs now drain every subscriber and every
|
||||
queued owner edge before aggregating failures, so one faulty sink cannot
|
||||
strand lights/particles or leak a stale edge into GUID reuse. Rebucket and
|
||||
withdrawal finish their canonical cell, projection, and presentation-index
|
||||
commits before rethrowing those observer aggregates.
|
||||
|
||||
The deterministic gate now validates the exact recall action ID and its
|
||||
animation-hook/PES route plus Hidden/remote-placement/UnHide ownership. Installed
|
||||
DAT colors, trail/cloud appearance, remote portal observation, and impact-origin
|
||||
presentation remain visual acceptance items; an in-memory conformance fixture
|
||||
cannot claim pixel appearance.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue