Standby culling
Park distant objects out of the engine network by player proximity, without losing their script state.
Overview
sbs.push_to_standby_list_id removes an object from the engine sim and network
replication while its py-side Agent (roles, links, inventory) persists — so
distant, irrelevant objects stop costing the network without losing script state.
This module drives that by player proximity: call standby_cull_step (or
standby_cull_fleets) each tick, and any candidate with no __player__ within a
radius is parked; it's retrieved the moment a player comes near.
A parked self-brained NPC has its brain paused while parked (and resumed on retrieve), so a non-simulated object isn't still being steered — which makes terrain and self-brained NPCs/POIs safe to cull. Fleets park as a unit: all of a fleet's ships and its one brain go dark together when no player is near any of them.
Side-agnostic — proximity is measured to every player. Extracted from the Open Universe's culler so any large-world mission can reuse it.
Quick example
== cull_loop ==
--- tick
await delay_sim(1)
standby_cull_step(role("__npc__") | role("terrain"), 30000)
standby_cull_fleets("fleet", 30000)
jump tick
from sbs_utils.procedural.standby import (
standby_cull_step, standby_cull_fleets, standby_cull_clear)
# each tick: park loose objects and whole fleets past 30k units from all players
standby_cull_step(candidates, 30000)
standby_cull_fleets("fleet", 30000)
Clear before you despawn
Before clearing a system (e.g. on a jump), call standby_cull_clear() first.
Delete-by-box only sees objects in normal space, not standby — so parked
objects must be retrieved before the region is cleared, or they leak.
API
Engine-network culling by player proximity.
sbs.push_to_standby_list_id removes an object from the engine sim + network
replication while its py-side Agent (roles/links/inventory) persists - so
distant, irrelevant objects stop costing the network without losing script
state. (physics/replication iterate sim.space_objects; standby pulls the object
out of it.)
Brains are MAST tasks independent of the sim, so a parked NPC's brain would keep
acting on a non-simulated object - so the culler pauses a parked object's brain
(brain_pause) and resumes it on retrieve. That makes terrain AND self-brained
NPCs/POIs safe to cull. A parked object isn't in normal space, so its position is
cached here.
Cull the fighters, not the rocks. Standby only pays off for objects that cost
the engine sim/network continuously - moving, brained, per-tick-replicating NPCs
and fleets. It is a poor fit for terrain:
* Engine tick cost of passive terrain is near-zero (measured: ~100k passive agents
held real-time; see OpenUniverse/MULTI_SYSTEM_FEASIBILITY.md).
* Terrain replicates to a client once, then only on a forced update - so there is
no ongoing network cost for standby to save.
* The py-side Agent persists while parked, so standby never shrinks the Python
heap / GC pressure regardless.
And it is net-negative for terrain: retrieve re-inserts the object into sim +
network, so crossing the radius re-sends parked terrain to in-range clients (a
network burst + pop-in hitch) that resident terrain never incurs. So although
terrain is safe to cull, prefer to leave it resident and aim the culler at active
content (standby_cull_fleets is the valuable path). Terrain standby is justified
only as an engine-side memory measure for genuinely dormant, far, unlikely-to-be-
visited systems - not as a per-tick or network optimization.
(Caveat: the perf run that grounds "terrain is cheap" had NO connected clients, so it
measured compute only - the NETWORK axis, which is standby's whole reason to exist,
is unmeasured. The "terrain replicates once, then only on force" model and the
retrieve-re-sends churn cost are reasoned, not measured. So the compute + heap
legs of "leave terrain resident" are solid; the network leg is a hypothesis - verify
with a client-connected run before relying on the churn-cost argument.)
Fleets are handled as a unit (standby_cull_fleets): a fleet's brain lives on the
fleet agent, not its ships (linked via a "ship_list" role/link), so all a fleet's
ships park/retrieve together and the one fleet brain pauses/resumes - the whole
formation goes dark when no player is near any of its ships.
Extracted from the Open Universe's culler so any large-world mission can reuse it.
Side-agnostic: proximity is measured to every __player__.
standby_cull_clear()
Retrieve everything parked and forget it - call before clearing a system on a jump, so parked terrain returns to normal space and gets despawned with the rest (delete-by-box only sees objects in normal space, not standby).
standby_cull_count()
How many objects are currently parked (diagnostics): loose objects + fleet ships.
standby_cull_fleets(fleet_role, radius)
Park/retrieve whole fleets by proximity. A fleet (an agent with fleet_role
whose ships are linked under "ship_list") is parked when no player is within
radius of ANY of its ships: every ship goes to standby and the fleet's brain
is paused (it lives on the fleet agent). It is retrieved the moment a player
comes near. Treating the formation as one unit keeps the fleet brain from
steering non-simulated ships.
standby_cull_step(candidates, radius)
Park candidates with no player within radius (out of the engine
network); retrieve parked ones once a player comes near. candidates is an
iterable of Agents (e.g. a role set); non-space agents that share a role are
skipped. A parked self-brained NPC has its brain paused while parked.