# Retail landblock/object retirement and portal blocking — pseudocode **Purpose:** Oracle boundary for Modern Runtime Slice E. ## Named-retail sources - `CLandBlock::destroy_static_objects @ 0x0052FA50` - `CLandBlock::Destroy @ 0x0052FAA0` - `CObjectMaint::DestroyObjects @ 0x00508C30` - `CObjectMaint::AddObjectToBeDestroyed @ 0x00508F70` - `SmartBox::UseTime @ 0x00455410` - `gmSmartBoxUI::UseTime @ 0x004D6E30` The Sept 2013 named pseudo-C is the behavioral oracle. WorldBuilder has no equivalent live-client teardown scheduler; its extracted mesh/cache owners are implementation references only. ## `CLandBlock::destroy_static_objects` ```text for i = 0 .. num_static_objects - 1: object = static_objects[i] if object != null: object.leave_world() delete object num_static_objects = 0 ``` The operation is synchronous in retail. Each object leaves the world before its memory is destroyed. ## `CLandBlock::Destroy` ```text destroy_static_objects() destroy_buildings() if landblock_info != null: landblock_info.Release() landblock_info = null closest = invalid lbi_exists = false direction = unknown if draw_array != null: delete[] draw_array draw_array = null draw_array_size = 0 ``` Retail does not expose a partially active destroyed landblock. The visible, spatial, ticking, and memory lifetimes end in one call. ## `CObjectMaint::DestroyObjects` ```text for every physics object: object.exit_world() object.leave_world() remove object from object_table remove object from null_object_table remove object from destruction schedule object.unset_parent() object.unparent_children() delete object for every weenie object: remove from weenie tables delete object destroy all object/null/weenie/inventory tables destroy lost-cell table ``` Again, execution is complete once begun. Parent/child and spatial withdrawal precede physical deletion. ## `CObjectMaint::AddObjectToBeDestroyed` ```text remove any prior destruction schedule for object_id deadline = Timer.cur_time + 25 seconds destruction_table[object_id] = deadline destruction_priority_queue.Insert(deadline, object_id) ``` This queue delays *when* complete object destruction begins. It is not precedent for leaving an object active while destroying it one field at a time. Acdream's 25-second nonresident live-object lifetime already ports this separate behavior. ## `SmartBox::UseTime` ```text if cell_manager.blocking_for_cells == false: if not all_cells_available and CheckPrefetchStatus(): CellManager.UpdateLoadPoint() if player exists and player has a cell: CellManager.ChangePosition(player.position) if player exists and not waiting_for_teleport and not position_update_complete: position_update_complete = true has_been_teleported = true ObjectMaint.UseTime() Physics.UseTime() GameTime.UseTime() LScape.UseTime() Ambient.UseTime() else: CellManager.CheckPrefetchStatus() SceneTool.Think() drain inbound SmartBox event queue CommandInterpreter.UseTime() Render.CalcDegLevel() ``` While retail is blocked for destination cells, the old world does not advance object maintenance, physics, landscape, game time, or ambient sound. UI/event dispatch and the portal presentation continue. This is the retail basis for Slice E's immediate old-generation quiesce. ## `gmSmartBoxUI::UseTime` portal wait presentation The portal `CreatureMode` remains live while `SmartBox` is blocked. Its camera continues one random roll segment at a time: ```text if now >= rotationStart + rotationDuration: currentAngle = rotationEndAngle rotationStart = now rotationDuration = RandomUniform(0.6, 1.8) seconds rotationStartAngle = currentAngle rotationEndAngle = RandomUniform(0, 360) degrees ECM_UI.SendNotice_DisplayStringInfo( channel = 0x1A, text = "In Portal Space - Please Wait...") else: level = UIGlobals.GetAnimLevel( (now - rotationStart) / rotationDuration) currentAngle = Lerp( rotationStartAngle, rotationEndAngle, level / 1024) CreatureMode.SetCameraDirection_Degrees((0, currentAngle, 0)) ``` The notice is a centered UI display string, not chat. Slice E's asynchronous adaptation delays its first projection until the recorded five-second reveal stall threshold, then repeats it on the same rotation-segment boundary while the authored tunnel keeps animating. ## Acdream asynchronous adaptation Retail performs each teardown synchronously and can synchronously block cell loading. Acdream prepares content on a worker and must not spend an unbounded render/update frame reproducing that transaction. The faithful observable contract is therefore split at a different boundary: ```text begin destination generation: mark prior world generation unavailable replace normal world viewport with portal presentation freeze old-generation object/static/effect simulation silence old-generation audio reject old generation from collision, picking, radar, and targeting at the shared-origin transaction boundary: atomically swap the complete old spatial generation out of reach retain one exact teardown receipt per old landblock over later update/resource-maintenance frames: release scripts/effects/lights/plugin projections release CPU owners admit renderer retirement; physical GL release remains fence delayed in parallel, under reserved destination budgets: admit destination completions publish collision and required Near render state request/upload required assets reveal only when the one destination-generation readiness state proves: collision root ready required Near scene ready required composite textures ready camera/player identity belongs to destination generation if the portal reveal is still incomplete after five seconds: keep the DAT-authored portal scene animating display the centered retail wait notice emit one generation-scoped diagnostic do not materialize early ``` Release-later never means run-later: an old owner may retain memory until its cursor runs, but it cannot keep simulating, colliding, rendering, targeting, or emitting audible work after the generation-quiesce edge. The shared-origin commit barrier is the completion of **spatial detachment**, not completion of every deferred resource release: ```text capture exact old landblock/entity teardown receipts clear the old loaded/pending/traversal/collision-visible spatial indexes repark nonpersistent live projections by their canonical landblock rescue the persistent local-player projection publish the resulting live visibility edges once once that single spatial-generation swap commits: recenter the shared coordinate origin configure and enqueue the destination window on later frames: destination publication uses its reserved work lane old retirement receipts use remaining cleanup capacity a publication for landblock X waits only while X has an older receipt the exact receipt for destination X may advance ahead of unrelated FIFO ordinary publication continues when no destination result is available ``` The per-landblock publication fence makes key-based terrain, physics, EnvCell, building, mesh-reference, and static-presentation cleanup safe: a late old receipt cannot remove a replacement owner with the same landblock key. Live objects are different. Their logical owner survives spatial withdrawal and may be reprojected immediately at the destination, so deferred landblock retirement must never clear a live object's lighting or translucency by reusable local ID. Live cell-scoped lighting is withdrawn by the incarnation-aware projection-visibility edge; logical translucency stays with the live record until its actual teardown. Landblock receipts clean only DAT-static entity presentation. This swap is deliberately one **atomic oversized progress operation** in the modern frame meter. Splitting it into 625 budgeted landblock detach admissions created a five-second portal stall even though the old generation was already quiesced and no intermediate subset was observable. The atomic work scans the small live-projection index, clears the old spatial maps, and transfers their existing entity lists into receipts; it does not synchronously destroy every static resource. Expensive script, renderer, physics, light, plugin, and GL cleanup still advances through the ordinary retryable receipt cursors. ## Port constraints 1. Preserve existing exact retry receipts; successful stages never replay. 2. FIFO is stable within priority and generation. 3. A time limit is checked between atomic owner operations. If one atomic operation itself exceeds its ceiling, diagnostics name that operation; it is then split at its natural cursor rather than interrupted mid-mutation. 4. No deferred callback may mutate GL from a worker. 5. Destination-critical work receives a reserved share of each frame; it does not bypass all budgets. 6. A reveal delay beyond retail's five-second fade ceiling keeps the portal tunnel active and displays the retail wait cue. It never reveals an incomplete world.