acdream/docs/research/2026-07-24-retail-streaming-retirement-pseudocode.md
Erik 2ff8f844b0 perf(streaming): reserve destination reveal capacity
Join destination scheduling to the canonical reveal generation, protect its share across every typed frame-budget dimension, and prevent stale work from clearing a replacement reservation. Remove forced incomplete materialization and project retail's centered portal wait cue while the authored tunnel remains active.

Tests: Release build clean; 91 focused reservation/reveal tests; full solution 8,158 passed, 5 skipped.

Co-authored-by: Codex <noreply@openai.com>
2026-07-24 19:39:23 +02:00

215 lines
6.8 KiB
Markdown

# 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
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
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.
## 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.