5.4 KiB
Retail landblock/object retirement and portal blocking — pseudocode
Purpose: Oracle boundary for Modern Runtime Slice E.
Named-retail sources
CLandBlock::destroy_static_objects @ 0x0052FA50CLandBlock::Destroy @ 0x0052FAA0CObjectMaint::DestroyObjects @ 0x00508C30CObjectMaint::AddObjectToBeDestroyed @ 0x00508F70SmartBox::UseTime @ 0x00455410
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
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
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
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
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
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.
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:
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
over later update/resource-maintenance frames:
detach old landblocks through exact retry receipts
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
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.
Port constraints
- Preserve existing exact retry receipts; successful stages never replay.
- FIFO is stable within priority and generation.
- 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.
- No deferred callback may mutate GL from a worker.
- Destination-critical work receives a reserved share of each frame; it does not bypass all budgets.
- 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.