Jump to content

OpenSimulator Internals/Code Map/Scene: Difference between revisions

From Open Simulator Technical Help
Jwbshaw (talk | contribs)
first
 
Jwbshaw (talk | contribs)
updates
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
= OpenSimulator Internals/Code Map/OpenSim =
= OpenSimulator Internals/Code Map/Scene =


== Overview ==
== Overview ==


OpenSim.exe is the region simulator process. It loads configuration, initialises the physics and script engines, loads region modules, connects to ROBUST services, and runs one or more regions.
Scene is the central object of the region simulator. One Scene instance exists per region. It holds all in-world state and coordinates between the physics engine, script engine, client connections, storage, and grid services.


In standalone mode, service implementations run in-process. In grid mode, service connectors make HTTP calls to ROBUST. The same code runs both ways -- only the config differs.
Class hierarchy:


Class hierarchy:
Scene → SceneBase → RegionApplicationBase
 
Source: OpenSim/Region/Framework/Scenes/Scene.cs
 
Scene.cs is a partial class -- additional methods are in other files in the same directory.
 
----
 
== Constructor ==
 
Two constructors:
 
Scene(RegionInfo regInfo)  -- base constructor
Scene(RegionInfo, AgentCircuitManager, ISimulationDataService, IEstateDataService, IConfigSource, string version)  -- full constructor
 
Base constructor:
# Creates SceneGraph (holds all entities and physics)
# Hooks SceneGraph.UnRecoverableError -- triggers RestartNow() on physics crash
# Sets defaults: PhysicalPrims=true, CollidablePrims=true, PhysicsEnabled=true, AllowAvatarCrossing=true, PeriodicBackup=true
# Creates EventManager
# Creates ScenePermissions
 
Full constructor (called from OpenSimBase.CreateScene()):
# Loads RegionSettings from SimulationDataService -- sets default terrain textures if missing, copies classic textures to PBR slots if PBR not set
# Loads EstateSettings from EstateDataService
# Creates SceneGridInfo from config and ServerURI
# Hooks EventManager land object events to SimulationDataService storage
# Reads [Startup] config -- draw distances, prim limits, physics flags, script engine, persistence timings, frame rate, viewer allow/deny lists, coarse location update interval, terrain update interval, backup interval
# Reads [EntityTransfer] config -- AllowAvatarCrossing, DisableObjectTransfer
# Reads [InterestManagement] config -- update prioritization scheme, reprioritization settings, object culling by distance
# Creates SimStatsReporter
# Starts timer watchdog
 
----
 
== Service References ==
 
All grid services are accessed through lazy-loaded properties backed by RequestModuleInterface<T>(). They throw if the service is not available (except EstateDataServiceSafe which returns null).
 
{| class="wikitable"
! Property !! Interface !! Notes
|-
| AssetService || IAssetService || throws if missing
|-
| InventoryService || IInventoryService || throws if missing, with detailed error message about config
|-
| GridService || IGridService || throws if missing
|-
| SimulationDataService || ISimulationDataService || throws if missing
|-
| EstateDataService || IEstateDataService || throws if missing
|-
| UserAccountService || IUserAccountService || null if missing
|-
| PresenceService || IPresenceService || null if missing
|-
| AuthenticationService || IAuthenticationService || null if missing
|-
| AvatarService || IAvatarService || null if missing
|-
| GridUserService || IGridUserService || null if missing
|-
| AgentPreferencesService || IAgentPreferencesService || null if missing
|-
| AuthorizationService || IAuthorizationService || null if missing
|-
| LibraryService || ILibraryService || null if missing
|-
| SimulationService || ISimulationService || null if missing
|}


OpenSim → OpenSimBase → RegionApplicationBase
Module references (set by SetModuleInterfaces() after modules load):


Source repository: https://github.com/opensim/opensim
{| class="wikitable"
! Property !! Interface
|-
| EntityTransferModule || IEntityTransferModule -- teleport and region crossing
|-
| AttachmentsModule || IAttachmentsModule
|-
| AgentTransactionsModule || IAgentAssetTransactions
|-
| UserManagementModule || IUserManagement
|-
| AvatarFactory || IAvatarFactoryModule
|-
| CapsModule || ICapabilitiesModule
|}


----
----


=== Entry Point ===
== The Main Loop (Heartbeat) ==


OpenSim/Region/Application/OpenSim.cs -- class OpenSim, StartupSpecific()
The scene runs one thread: the Heartbeat thread. Started by Start():


OpenSim.cs handles the interactive simulator layer:
Heartbeat()
  TriggerOnRegionStarted()
  Update(1)  -- first frame, watchdog not yet active
  Watchdog alarm enabled
  Update(-1)  -- runs until shutdown


# Sets up console -- local, basic, rest, or GUI-driven based on config
Update() loop runs once per frame:
# Calls base.StartupSpecific() (see OpenSimBase below)
# Registers HTTP handlers on MainServer.Instance:
#* /simstatus -- returns "OK"
#* /SHA1(osSecret) -- extended stats JSON
#* /userStatsURI -- stats at user-configured path (optional)
#* /robots.txt -- returns "# go away, Disallow: /"
#* /index.php -- IndexPHPHandler for viewer login and capability discovery
# Optional: registers managed stats endpoint
# Hooks watchdog timeout handler
# Prints startuplogo.txt if present
# Selects default console region (root if multiple, the single region if only one)
# Runs startup command script if configured
# Starts timed script timer if configured


Console commands registered: force update, change region, save/load xml/xml2/oar, edit scale, rotate/scale/translate scene, kick user, show users/connections/circuits/pending-objects/modules/regions/ratings, backup, create region, restart (disabled), command-script, remove-region, delete-region, estate create/set owner/set name/link region.
Per frame (every frame unless noted):
# CheckTerrainUpdates() -- every 4 frames
# UpdateTerrain() -- every m_update_terrain frames (default 1000)
# UpdatePreparePhysics() -- physics pre-step
# SendCoarseLocations() -- every 5 frames, async via thread pool
# UpdatePhysics(FrameTime) -- main physics step, returns physicsFPS
# CheckAtTargets() -- check llMoveToTarget / llRotLookAt
# UpdateObjectGroups() -- send queued object updates to clients
# UpdatePresences() -- send presence updates to clients
# CleanTempObjects() -- every 180 frames, async
# UpdateEvents() -- fires EventManager.OnFrame
# UpdateStorageBackup() -- every 200 frames, async
# Frame 20: enable logins, inform neighbours region is up, set Ready=true, GC compact


Note: restart command is registered but disabled -- marked unreliable in the source.
Frame timing: FrameTime defaults to 0.0908s (~11fps). Sleep is calculated to hit target frame time. Stats normalized to 55fps for viewer display.


Shutdown: runs shutdown command script if configured, disposes timed script timer, calls base.ShutdownSpecific().
Backup runs asynchronously every 200 frames. Objects are only persisted if they have been changed for at least MinimumTimeBeforePersistenceConsidered (default 60s) and no longer than MaximumTimeBeforePersistenceConsidered (default 600s).


----
----


=== OpenSimBase ===
== Startup Sequence (called from OpenSimBase.CreateRegion) ==
 
After construction:
 
# scene.SetModuleInterfaces() -- wires up module references from loaded region modules
# loadAllLandObjectsFromStorage() -- loads parcels from region database
# LoadPrimsFromStorage() -- loads all objects, calls AddRestoredSceneObject() for each
# RegisterRegionWithGrid() -- calls GridService.RegisterRegion(), throws on failure
# CreateScriptInstances() -- starts script engine for all loaded objects
# scene.Start() -- starts Heartbeat thread


OpenSim/Region/Application/OpenSimBase.cs -- class OpenSimBase
AllModulesLoaded() is called after all modules are loaded. Pushes simulator feature data to ISimulatorFeaturesModule (FPS, prim limits, grid info, search URL, etc).


StartupSpecific() sequence:
----


# Refuses to run if CombineContiguousRegions (MegaRegions) is set -- explicitly unsupported, fatal exit
== Region Crossing and Teleport ==
# Creates PID file if configured
# Reads Stats_URI, SecurePermissionsLoading, permission modules, managed stats config from [Startup]
# Loads SimulationDataStore plugin from [SimulationDataStore] -- throws if missing
# Loads EstateDataStore plugin from [EstateDataStore] or [EstateService] -- throws if missing
# Calls base.StartupSpecific() -- see RegionApplicationBase
# Loads application plugins from /OpenSim/Startup extension point
# Calls PostInitialise() on all plugins
# Adds plugin commands to console


Initialize() sequence (called from base.StartUp()):
All teleport and crossing logic is delegated to EntityTransferModule:


# Starts WorkManager.JobEngine if enabled
RequestTeleportLocation()  →  EntityTransferModule.Teleport()
# Handles SSL cert creation or renewal if configured
CrossAgentToNewRegion()    →  EntityTransferModule.Cross()
# Handles PEM to PKCS12 cert conversion if configured
TeleportClientHome()      →  EntityTransferModule.TeleportHome()
# Sets HTTP server port and SSL flag from [Network]
 
# Hooks SceneManager.OnRestartSim
Incoming objects and attachments from crossings:
# Enables MemoryWatchdog and Watchdog only when all regions are ready -- avoids false positives during startup
 
IncomingCreateObject()    →  EntityTransferModule.HandleIncomingSceneObject()
IncomingAttechments()      →  EntityTransferModule.HandleIncomingAttachments()
 
Note: IncomingAttechments() -- the typo is in the source. See WTF file.
 
OtherRegionUp() is called when a neighbouring region comes online. If within border distance, enables child agents in that region for all current root avatars via EntityTransferModule.EnableChildAgent().


----
----


=== Region Creation ===
== Avatar Connection (NewUserConnection) ==
 
Called by the login service or another simulator to initiate a connection. Not triggered by the viewer directly.


OpenSim/Region/Application/OpenSimBase.cs -- CreateRegion()
# Checks logins enabled
# Checks viewer allow/deny lists
# Handles existing ScenePresence (zombie root agents, race conditions during teleport)
# Clamps start position within region bounds
# CheckLandPositionAccess() -- checks telehub, parcel access, agent limit
# VerifyUserPresence() -- checks PresenceService for active session
# AuthorizeUser() -- checks estate ban, public access, access list, group membership
# Sets up CAPS via CapsModule
# ActivateCaps()


Called once per region on startup, and again on restart. Sequence:
Connection is activated later when the viewer sends UseCircuitCodePacket UDP packet.


# Gets IRegionModulesController from ApplicationRegistry -- fatal exit if missing
----
# Sets region ServerURI from ExternalHostName and HTTP port
# Calls SetupScene() -- creates AgentCircuitManager and Scene instance (see Scene below)
# Calls controller.AddRegionToModules(scene) -- loads all region modules
# Verifies required permissions modules are loaded if SecurePermissionsLoading = true -- fatal exit if missing
# Calls scene.SetModuleInterfaces() -- wires up module references
# Calls SetUpEstateOwner() if estate has no owner -- prompts console interactively
# Calls scene.loadAllLandObjectsFromStorage() -- loads parcels from region database
# Calls scene.LoadPrimsFromStorage() -- loads all objects from region database
# Adds RegionStatsSimpleHandler to MainServer
# Calls scene.RegisterRegionWithGrid() -- registers with ROBUST GridService -- fatal exit on failure
# Calls scene.CreateScriptInstances() -- starts script engine for loaded objects
# Adds scene to SceneManager
# Hooks scene.EventManager.OnShutdown


Estate owner setup (SetUpEstateOwner()):
== Avatar Removal (RemoveClient) ==
* Checks [Estates] config for DefaultEstateOwnerName, UUID, email, password
* If not found, prompts console interactively
* If user does not exist and UserAccountService is a local service, creates the user account
* Stores estate settings with owner UUID


PopulateRegionEstateInfo():
# Sends shutdown notice to child agents if root
* Loads estate settings for region from database
# Avatar stands up if seated
* If no estate assigned: checks TargetEstate in Regions.ini, then DefaultEstateName in [Estates] config, then prompts console interactively
# Closes child agent connections on neighbouring regions (async)
* Can create a new estate or join an existing one
# Triggers ClientClosed and OnRemovePresence events
# De-rezzes attachments (root only)
# Sends KillObject to all clients
# Removes agent transactions
# Removes circuit, scene presence, client manager entry, CAPS


----
----


=== Scene Creation ===
== Shutdown (Close) ==


OpenSim/Region/Application/OpenSimBase.cs -- SetupScene() → CreateScene()
# Deregisters from GridService
# Kicks all root avatars with shutdown message
# Sets m_shuttingDown = true
# Sleeps 500ms to let kick messages reach clients
# Closes all agents
# Triggers SceneShuttingDown event
# Backup(true) -- force persist all pending changes
# Closes SceneGraph
# Disposes PhysicsScene last (scripts may reference physics during shutdown)


protected Scene SetupScene(RegionInfo regionInfo, int proxyOffset, IConfigSource configSource)
----
{
    AgentCircuitManager circuitManager = new AgentCircuitManager();
    Scene scene = CreateScene(regionInfo, m_simulationDataService, m_estateDataService, circuitManager);
    scene.LoadWorldMap();
    return scene;
}


protected override Scene CreateScene(...)
== Object Management ==
{
    return new Scene(regionInfo, circuitManager, simDataService, estateDataService, Config, m_version);
}


Scene constructor takes: RegionInfo, AgentCircuitManager, ISimulationDataService, IEstateDataService, IConfigSource, version string.
Key methods:


See [[OpenSimulator Internals/Code Map/Scene]] for Scene internals.
{| class="wikitable"
! Method !! Notes
|-
| AddNewPrim() || Creates a new prim via raycast. Checks permissions. Uses entity creator registry if available, else creates SceneObjectGroup directly. Applies user default permissions from AgentPreferencesService.
|-
| AddRestoredSceneObject() || Adds object loaded from storage. Delegates to SceneGraph.
|-
| AddNewSceneObject() || Adds newly created object. Delegates to SceneGraph. Triggers ObjectAddedToScene event.
|-
| DeleteSceneObject() || Removes scripts, keyframe motion, email listeners, physics actors. Unlinks from scene. Triggers ObjectBeingRemovedFromScene.
|-
| UnlinkSceneObject() || Removes record from scene without destroying. On hard delete, removes from database.
|-
| IncomingCreateObject() || Handles object arriving from region crossing. Delegates to EntityTransferModule.
|-
| ForceSceneObjectBackup() || Synchronous backup of a single object. Used for deletes and link/unlink.
|}


----
----


=== Config Loading ===
== Client Event Subscriptions ==


OpenSim/Region/Application/OpenSimBase.cs -- LoadConfigSettings()
SubscribeToClientEvents() wires all viewer protocol events to scene handlers:
OpenSim/Region/Framework/ConfigurationLoader.cs


Same layered config mechanism as ROBUST. Config loaded via ConfigurationLoader.LoadConfigSettings(). Architecture selected via Include-Architecture in OpenSim.ini -- determines standalone vs grid mode.
* Terrain events (currently empty)
* Prim events: position, rotation, scale, shape, texture, name, material, link/unlink, duplicate, permissions, grab, spin, undo/redo
* Prim rez events: OnAddPrim → AddNewPrim(), OnRezObject → RezObject()
* Inventory events: folder and item CRUD, task inventory, rez script
* Teleport events: OnTeleportLocationRequest → RequestTeleportLocation()
* Script events: reset, get/set running
* Parcel events: return objects, set clean time, buy
* Grid events: money transfer
* Network events: stats update, viewer effect
 
Note: UnSubscribeToClientEvents() is defined but marked FIXME -- not called anywhere. See WTF file.


----
----


=== HTTP Handlers ===
== Health Monitoring ==


Registered on MainServer.Instance during startup:
GetHealth() returns an integer 1-5:


{| class="wikitable"
{| class="wikitable"
! Path !! Handler !! Notes
! Value !! Meaning
|-
|-
| /simstatus || SimStatusHandler || Returns "OK" -- health check
| 0 || Starting up
|-
|-
| /SHA1(osSecret) || XSimStatusHandler || Extended stats as JSON -- path is a hash for mild obscurity
| 1 || HTTP alive but heartbeat stopped -- possible lockup
|-
|-
| /userStatsURI || UXSimStatusHandler || Same stats at user-configured path -- optional
| 2 || Heartbeat running (frame tick < 4s ago)
|-
|-
| /robots.txt || SimRobotsHandler || Blocks all web crawlers
| 3 || One packet thread running
|-
|-
| /index.php || IndexPHPHandler || Viewer login and capability discovery -- see [[OpenSimulator Internals/Code Map/Shared]]
| 4 || Both packet threads running
|-
| 5 || New user logged in within last 4 minutes
|}
|}
TimerWatchdog runs every second. Pushes health and root agent count to etcd if the IEtcdModule is present.
----
== Persistence ==
Objects are persisted via EventManager.OnBackup → SimulationDataService. Objects qualify for persistence if:
* HasGroupChanged = true
* Time since last change > MinimumTimeBeforePersistenceConsidered (default 60s)
* Time since last change < MaximumTimeBeforePersistenceConsidered (default 600s) OR forced=true
Auto-return queued in m_returns dictionary. Return messages sent via IMessageTransferModule on next backup cycle.


----
----


=== Shutdown ===
== Notable Details ==


ShutdownSpecific():
* MegaRegions (CombineContiguousRegions) are explicitly rejected on startup with a fatal error
# Sends XmlRpc Stop to proxy if configured
* The restart console command is registered but disabled -- marked unreliable in source
# Calls SceneManager.Close() -- closes all scenes
* IncomingAttechments() has a typo -- see WTF file for both file locations
# Disposes all application plugins
* GOTO is used in AuthorizeUser() for group access checks -- commented in source as "some say GOTO is ugly"
# Calls base.ShutdownSpecific()
* Heartbeat restart limit: if heartbeat thread dies and restarts more than 10 times, Environment.Exit(1)
* GC.Collect() is called explicitly at frame 20 and on map tile regeneration
* etcd integration is optional -- IEtcdModule only -- used for external health monitoring


----
----
Line 170: Line 302:


* [[OpenSimulator Internals/Code Map]]
* [[OpenSimulator Internals/Code Map]]
* [[OpenSimulator Internals/Code Map/ROBUST]]
* [[OpenSimulator Internals/Code Map/OpenSim]]
* [[OpenSimulator Internals/Code Map/ScenePresence]]
* [[OpenSimulator Internals/Code Map/EntityTransferModule]]
* [[OpenSimulator Internals/Code Map/HGEntityTransferModule]]
* [[OpenSimulator Internals/Code Map/AttachmentsModule]]
* [[OpenSimulator Internals/Code Map/AvatarFactoryModule]]
* [[OpenSimulator Internals/Code Map/InventoryAccessModule]]
* [[OpenSimulator Internals/Code Map/Shared]]
* [[OpenSimulator Internals/Code Map/Shared]]
* [[OpenSimulator Internals/Reading the Code]]
* [[OpenSimulator Internals/Architecture Overview]]
* [[OpenSimulator Internals/Architecture Overview]]
* [[OpenSimulator Internals/Connector Architecture]]
* [[OpenSimulator Internals/Connector Architecture]]
* [[OpenSimulator Internals/Walkthroughs/Avatar Rez In Region]]
* [[OpenSimulator Internals/Walkthroughs/Avatar Logs Out]]
* [[OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions]]

Latest revision as of 13:55, 7 July 2026

OpenSimulator Internals/Code Map/Scene

[edit]

Overview

[edit]

Scene is the central object of the region simulator. One Scene instance exists per region. It holds all in-world state and coordinates between the physics engine, script engine, client connections, storage, and grid services.

Class hierarchy:

Scene → SceneBase → RegionApplicationBase

Source: OpenSim/Region/Framework/Scenes/Scene.cs

Scene.cs is a partial class -- additional methods are in other files in the same directory.


Constructor

[edit]

Two constructors:

Scene(RegionInfo regInfo)  -- base constructor
Scene(RegionInfo, AgentCircuitManager, ISimulationDataService, IEstateDataService, IConfigSource, string version)  -- full constructor

Base constructor:

  1. Creates SceneGraph (holds all entities and physics)
  2. Hooks SceneGraph.UnRecoverableError -- triggers RestartNow() on physics crash
  3. Sets defaults: PhysicalPrims=true, CollidablePrims=true, PhysicsEnabled=true, AllowAvatarCrossing=true, PeriodicBackup=true
  4. Creates EventManager
  5. Creates ScenePermissions

Full constructor (called from OpenSimBase.CreateScene()):

  1. Loads RegionSettings from SimulationDataService -- sets default terrain textures if missing, copies classic textures to PBR slots if PBR not set
  2. Loads EstateSettings from EstateDataService
  3. Creates SceneGridInfo from config and ServerURI
  4. Hooks EventManager land object events to SimulationDataService storage
  5. Reads [Startup] config -- draw distances, prim limits, physics flags, script engine, persistence timings, frame rate, viewer allow/deny lists, coarse location update interval, terrain update interval, backup interval
  6. Reads [EntityTransfer] config -- AllowAvatarCrossing, DisableObjectTransfer
  7. Reads [InterestManagement] config -- update prioritization scheme, reprioritization settings, object culling by distance
  8. Creates SimStatsReporter
  9. Starts timer watchdog

Service References

[edit]

All grid services are accessed through lazy-loaded properties backed by RequestModuleInterface<T>(). They throw if the service is not available (except EstateDataServiceSafe which returns null).

Property Interface Notes
AssetService IAssetService throws if missing
InventoryService IInventoryService throws if missing, with detailed error message about config
GridService IGridService throws if missing
SimulationDataService ISimulationDataService throws if missing
EstateDataService IEstateDataService throws if missing
UserAccountService IUserAccountService null if missing
PresenceService IPresenceService null if missing
AuthenticationService IAuthenticationService null if missing
AvatarService IAvatarService null if missing
GridUserService IGridUserService null if missing
AgentPreferencesService IAgentPreferencesService null if missing
AuthorizationService IAuthorizationService null if missing
LibraryService ILibraryService null if missing
SimulationService ISimulationService null if missing

Module references (set by SetModuleInterfaces() after modules load):

Property Interface
EntityTransferModule IEntityTransferModule -- teleport and region crossing
AttachmentsModule IAttachmentsModule
AgentTransactionsModule IAgentAssetTransactions
UserManagementModule IUserManagement
AvatarFactory IAvatarFactoryModule
CapsModule ICapabilitiesModule

The Main Loop (Heartbeat)

[edit]

The scene runs one thread: the Heartbeat thread. Started by Start():

Heartbeat()
  TriggerOnRegionStarted()
  Update(1)  -- first frame, watchdog not yet active
  Watchdog alarm enabled
  Update(-1)  -- runs until shutdown

Update() loop runs once per frame:

Per frame (every frame unless noted):

  1. CheckTerrainUpdates() -- every 4 frames
  2. UpdateTerrain() -- every m_update_terrain frames (default 1000)
  3. UpdatePreparePhysics() -- physics pre-step
  4. SendCoarseLocations() -- every 5 frames, async via thread pool
  5. UpdatePhysics(FrameTime) -- main physics step, returns physicsFPS
  6. CheckAtTargets() -- check llMoveToTarget / llRotLookAt
  7. UpdateObjectGroups() -- send queued object updates to clients
  8. UpdatePresences() -- send presence updates to clients
  9. CleanTempObjects() -- every 180 frames, async
  10. UpdateEvents() -- fires EventManager.OnFrame
  11. UpdateStorageBackup() -- every 200 frames, async
  12. Frame 20: enable logins, inform neighbours region is up, set Ready=true, GC compact

Frame timing: FrameTime defaults to 0.0908s (~11fps). Sleep is calculated to hit target frame time. Stats normalized to 55fps for viewer display.

Backup runs asynchronously every 200 frames. Objects are only persisted if they have been changed for at least MinimumTimeBeforePersistenceConsidered (default 60s) and no longer than MaximumTimeBeforePersistenceConsidered (default 600s).


Startup Sequence (called from OpenSimBase.CreateRegion)

[edit]

After construction:

  1. scene.SetModuleInterfaces() -- wires up module references from loaded region modules
  2. loadAllLandObjectsFromStorage() -- loads parcels from region database
  3. LoadPrimsFromStorage() -- loads all objects, calls AddRestoredSceneObject() for each
  4. RegisterRegionWithGrid() -- calls GridService.RegisterRegion(), throws on failure
  5. CreateScriptInstances() -- starts script engine for all loaded objects
  6. scene.Start() -- starts Heartbeat thread

AllModulesLoaded() is called after all modules are loaded. Pushes simulator feature data to ISimulatorFeaturesModule (FPS, prim limits, grid info, search URL, etc).


Region Crossing and Teleport

[edit]

All teleport and crossing logic is delegated to EntityTransferModule:

RequestTeleportLocation()  →  EntityTransferModule.Teleport()
CrossAgentToNewRegion()    →  EntityTransferModule.Cross()
TeleportClientHome()       →  EntityTransferModule.TeleportHome()

Incoming objects and attachments from crossings:

IncomingCreateObject()     →  EntityTransferModule.HandleIncomingSceneObject()
IncomingAttechments()      →  EntityTransferModule.HandleIncomingAttachments()

Note: IncomingAttechments() -- the typo is in the source. See WTF file.

OtherRegionUp() is called when a neighbouring region comes online. If within border distance, enables child agents in that region for all current root avatars via EntityTransferModule.EnableChildAgent().


Avatar Connection (NewUserConnection)

[edit]

Called by the login service or another simulator to initiate a connection. Not triggered by the viewer directly.

  1. Checks logins enabled
  2. Checks viewer allow/deny lists
  3. Handles existing ScenePresence (zombie root agents, race conditions during teleport)
  4. Clamps start position within region bounds
  5. CheckLandPositionAccess() -- checks telehub, parcel access, agent limit
  6. VerifyUserPresence() -- checks PresenceService for active session
  7. AuthorizeUser() -- checks estate ban, public access, access list, group membership
  8. Sets up CAPS via CapsModule
  9. ActivateCaps()

Connection is activated later when the viewer sends UseCircuitCodePacket UDP packet.


Avatar Removal (RemoveClient)

[edit]
  1. Sends shutdown notice to child agents if root
  2. Avatar stands up if seated
  3. Closes child agent connections on neighbouring regions (async)
  4. Triggers ClientClosed and OnRemovePresence events
  5. De-rezzes attachments (root only)
  6. Sends KillObject to all clients
  7. Removes agent transactions
  8. Removes circuit, scene presence, client manager entry, CAPS

Shutdown (Close)

[edit]
  1. Deregisters from GridService
  2. Kicks all root avatars with shutdown message
  3. Sets m_shuttingDown = true
  4. Sleeps 500ms to let kick messages reach clients
  5. Closes all agents
  6. Triggers SceneShuttingDown event
  7. Backup(true) -- force persist all pending changes
  8. Closes SceneGraph
  9. Disposes PhysicsScene last (scripts may reference physics during shutdown)

Object Management

[edit]

Key methods:

Method Notes
AddNewPrim() Creates a new prim via raycast. Checks permissions. Uses entity creator registry if available, else creates SceneObjectGroup directly. Applies user default permissions from AgentPreferencesService.
AddRestoredSceneObject() Adds object loaded from storage. Delegates to SceneGraph.
AddNewSceneObject() Adds newly created object. Delegates to SceneGraph. Triggers ObjectAddedToScene event.
DeleteSceneObject() Removes scripts, keyframe motion, email listeners, physics actors. Unlinks from scene. Triggers ObjectBeingRemovedFromScene.
UnlinkSceneObject() Removes record from scene without destroying. On hard delete, removes from database.
IncomingCreateObject() Handles object arriving from region crossing. Delegates to EntityTransferModule.
ForceSceneObjectBackup() Synchronous backup of a single object. Used for deletes and link/unlink.

Client Event Subscriptions

[edit]

SubscribeToClientEvents() wires all viewer protocol events to scene handlers:

  • Terrain events (currently empty)
  • Prim events: position, rotation, scale, shape, texture, name, material, link/unlink, duplicate, permissions, grab, spin, undo/redo
  • Prim rez events: OnAddPrim → AddNewPrim(), OnRezObject → RezObject()
  • Inventory events: folder and item CRUD, task inventory, rez script
  • Teleport events: OnTeleportLocationRequest → RequestTeleportLocation()
  • Script events: reset, get/set running
  • Parcel events: return objects, set clean time, buy
  • Grid events: money transfer
  • Network events: stats update, viewer effect

Note: UnSubscribeToClientEvents() is defined but marked FIXME -- not called anywhere. See WTF file.


Health Monitoring

[edit]

GetHealth() returns an integer 1-5:

Value Meaning
0 Starting up
1 HTTP alive but heartbeat stopped -- possible lockup
2 Heartbeat running (frame tick < 4s ago)
3 One packet thread running
4 Both packet threads running
5 New user logged in within last 4 minutes

TimerWatchdog runs every second. Pushes health and root agent count to etcd if the IEtcdModule is present.


Persistence

[edit]

Objects are persisted via EventManager.OnBackup → SimulationDataService. Objects qualify for persistence if:

  • HasGroupChanged = true
  • Time since last change > MinimumTimeBeforePersistenceConsidered (default 60s)
  • Time since last change < MaximumTimeBeforePersistenceConsidered (default 600s) OR forced=true

Auto-return queued in m_returns dictionary. Return messages sent via IMessageTransferModule on next backup cycle.


Notable Details

[edit]
  • MegaRegions (CombineContiguousRegions) are explicitly rejected on startup with a fatal error
  • The restart console command is registered but disabled -- marked unreliable in source
  • IncomingAttechments() has a typo -- see WTF file for both file locations
  • GOTO is used in AuthorizeUser() for group access checks -- commented in source as "some say GOTO is ugly"
  • Heartbeat restart limit: if heartbeat thread dies and restarts more than 10 times, Environment.Exit(1)
  • GC.Collect() is called explicitly at frame 20 and on map tile regeneration
  • etcd integration is optional -- IEtcdModule only -- used for external health monitoring

See Also

[edit]