Jump to content

OpenSimulator Internals/Walkthroughs/Avatar Rez In Region

From Open Simulator Technical Help
Revision as of 12:58, 7 July 2026 by Jwbshaw (talk | contribs) (first)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

OpenSimulator Internals/Walkthroughs/Avatar Rez In Region

[edit]

Overview

[edit]

Traces what happens in code, connectors, and database from the moment a viewer completes login and connects to a region, through to the avatar standing in-world with appearance applied and scene state sent.

This covers the normal login case (not HG, not region transfer). See OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions and OpenSimulator Internals/Walkthroughs/Avatar Goes HG for those paths.


1. Login Service Issues Seed Capability

[edit]
OpenSim/Services/LLLoginService/LLLoginService.cs
OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
  1. Viewer POSTs login credentials to ROBUST LoginService (port 8002 by default) via XMLRPC.
  2. LLLoginService authenticates via AuthenticationService, loads UserAccount, fetches appearance via AvatarService.
  3. LoginService calls PresenceService.LoginAgent() -- writes presence row: UserID, RegionID, SessionID, SecureSessionID, Online=1.
  4. LoginService calls GridUserService.SetLastPosition() -- updates griduser: LastRegionID, LastPosition, Login timestamp.
  5. LoginService selects destination region via GridService -- reads from regions table.
  6. LoginService calls the destination region's NewUserConnection capability -- passes AgentCircuitData (agent UUID, session UUID, circuit code, appearance, teleport flags). This pre-populates AgentCircuitManager in the region before the viewer connects.
  7. LoginService returns login response to viewer: SimIP, SimPort, RegionX/Y, SeedCapability URL, circuit code, session UUIDs.
DB writes
  • presence -- INSERT or UPDATE: UserID, RegionID, SessionID, SecureSessionID, Online=1
  • griduser -- UPDATE: LastRegionID, LastPosition, Login timestamp

2. Viewer Establishes UDP Circuit

[edit]
OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
  1. Viewer sends UseCircuitCode packet to region UDP port.
  2. LLUDPServer.HandleUseCircuitCode() validates circuit code against AgentCircuitManager (pre-populated in step 1).
  3. On match: LLUDPClient created. LLClientView constructed and associated with the circuit.
  4. ScenePresence constructed:
    • IsChildAgent = true initially (set in constructor)
    • Constructor fetches UserAccount for god level and user flags
    • Constructor calls RegisterToClientEvents() -- wires OnCompleteMovementToRegion → CompleteMovement, OnAgentUpdate → HandleAgentUpdate, OnRegionHandShakeReply → RegionHandShakeReply, and others
    • Appearance set from AgentCircuitData appearance passed by LoginService
    • AdjustKnownSeeds() called -- initialises known neighbour region cap seeds
No DB writes at this step.

3. Viewer Sends CompleteMovementToRegion

[edit]
OpenSim/Region/Framework/Scenes/ScenePresence.cs -- CompleteMovement()

The viewer fires CompleteMovementToRegion after receiving the circuit acknowledgement. This triggers ScenePresence.CompleteMovement() on the region side.

  1. For login (IsRealLogin true): does NOT wait for UpdateAgent -- skips WaitForUpdateAgent(). For teleports and crossings: waits up to 10 seconds for the source region's UpdateAgent call to arrive before proceeding.
  2. Checks flying state from AgentControlFlags.
  3. Calls MakeRootAgent() (see step 4).
  4. If not a cross-update: fetches group title via IGroupsModule.
  5. Rotates avatar to look direction.
  6. Initialises parcel tracking (m_currentParcelUUID, m_currentParcelHide).
  7. Sets m_inTransit = false.
  8. Sends RegionHandshake to viewer (ControllingClient.SendRegionHandshake()) if not a crossing.
  9. Calls ControllingClient.MoveAgentIntoRegion() -- sends the viewer its position and look.
  10. Validates baked texture cache via AvatarFactory. Queues appearance save if invalid.
  11. Sends initial avatar data to all presences (SendInitialAvatarDataToAllAgents()).
  12. Sends this avatar's appearance to self (SendAppearanceToAgent(this)).
  13. Sends current animation pack to self.
  14. Sends appearance and animations to all other presences (parcel visibility respected).
  15. Rezzes attachments: for real login, calls Scene.AttachmentsModule.RezAttachments(this).
  16. For login (not cross-update): calls IFriendsModule.SendFriendsOnlineIfNeeded().
  17. Hooks RegionHeartbeatEnd event for per-frame health regen and movement animation updates.
No DB writes at this step (appearance save is queued async if needed).

4. MakeRootAgent()

[edit]
OpenSim/Region/Framework/Scenes/ScenePresence.cs -- MakeRootAgent()

Called from CompleteMovement(). This is the critical path; delay here delays the crossing.

  1. Acquires m_completeMovementLock. Returns false immediately if already root agent (IsChildAgent == false).
  2. Handles pending sit: if ParentUUID is set, resolves the sit target prim and re-seats the avatar.
  3. Sets IsChildAgent = false.
  4. Updates RegionHandle to this region.
  5. Fires EventManager.TriggerSetRootAgentScene().
  6. Position adjustment (if not sitting):
    • Checks and adjusts landing point (telehub, parcel landing point, ban lines) via CheckAndAdjustLandingPoint_OS() or _SL().
    • Clamps position to region bounds.
    • Raises position to ground height + avatar half-height.
    • If ViaLogin or ViaLocation flags set: raycasts downward from PhysSearchHeight (300m) to find surface, adjusts Z to avoid being inside objects.
    • Sets AbsolutePosition.
    • Calls AddToPhysicalScene(isFlying) -- creates PhysicsActor, enters physics simulation.
  7. Calls m_scene.SwapRootAgentCount(false, IsNPC) -- increments root agent count.
  8. Resets MovementFlags to 0.
  9. Updates circuit child status: AuthenticateHandler.UpdateAgentChildStatus(circuitCode, false).
  10. Fires EventManager.TriggerOnMakeRootAgent(this) -- modules hook here.
No DB writes at this step.

5. RegionHandshake / SendInitialData

[edit]
OpenSim/Region/Framework/Scenes/ScenePresence.cs -- RegionHandShakeReply(), SendInitialData()
  1. Viewer sends RegionHandshakeReply in response to the handshake sent in step 3.
  2. RegionHandShakeReply() sets m_gotRegionHandShake = true and NeedInitialData = 2.
  3. On subsequent heartbeat frames, Update() checks NeedInitialData > 0 and calls SendInitialData().
  4. SendInitialData() waits for viewer caps seeds to be sent (ViewerFlags.SentSeeds), then waits a few more frames for the viewer to process them (NeedInitialData incremented to 6 before proceeding).
  5. When ready, fires async via Util.FireAndForget:
    • Releases source region if callback URI present (v1 or v0.7 HG path).
    • Closes old child agents via IEntityTransferModule.CloseOldChildAgents().
    • Sends terrain layer data (Scene.SendLayerData()) if not a teleport.
    • Sends parcel info (LandChannel.sendClientInitialLandInfo()).
    • Sends full updates for all other root presences' avatars (SendOtherAgentsAvatarFullToMe()).
    • Sends ObjectUpdate packets for all scene objects within draw distance -- either full updates or cache probes depending on viewer cache state.
    • Creates child agents in neighbouring regions via IEntityTransferModule.EnableChildAgents(this).
    • Enables child update processing (m_childUpdatesBusy = false).
No DB writes at this step.

6. Attachments Rezzed

[edit]
OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs -- RezAttachments()

Called from CompleteMovement() for real logins (IsRealLogin true). For teleports/crossings, attachments are carried in AgentData and scripts restarted via RestartAttachmentScripts() instead.

  1. For each attachment in appearance data: fetches inventory item from InventoryService.
  2. Fetches asset from AssetService.
  3. Rezzes SceneObjectGroup in world at attachment point.
  4. Note: method name typo IncomingAttechments() exists at Scene.cs line 2976 and AttachmentsModule.cs line 384 (Mantis pending).
DB reads
  • inventoryitems -- SELECT by item UUID for each attachment

7. Presence and GridUser Updated

[edit]
OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs

After MakeRootAgent and CompleteMovement complete, the region confirms the avatar's position:

  1. PresenceService.ReportAgent() -- updates presence table, confirms RegionID.
  2. GridUserService.SetLastPosition() -- updates griduser with confirmed in-region position and look.
DB writes
  • presence -- UPDATE: RegionID confirmed for this session
  • griduser -- UPDATE: LastPosition, LastLookAt, LastRegionID

Summary: DB Tables Touched

[edit]
Table Operation Step
presence INSERT/UPDATE LoginService (step 1)
griduser UPDATE LoginService (step 1), post-rez (step 7)
regions SELECT LoginService destination lookup (step 1)
avatarappearance SELECT LoginService via AvatarService (step 1)
avatarattachments SELECT LoginService via AvatarService (step 1)
inventoryitems SELECT AttachmentsModule.RezAttachments() (step 6)

Note: avatarappearance and avatarattachments are read by LoginService, not by the region directly -- the appearance data travels to the region inside AgentCircuitData.


Key Flags

[edit]
  • TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID -- set for normal login. Controls landing point behavior, telehub routing, and whether WaitForUpdateAgent() is skipped.
  • TeleportFlags.ViaHGLogin -- HG login path; triggers different appearance handling and skips baked texture validation.
  • IsRealLogin() -- returns true only for ViaLogin without ViaHGLogin. Determines whether attachments are freshly rezzed vs carried from source region.
  • m_gotCrossUpdate -- false for login, true for region crossings. Controls whether SendLayerData and child agent setup are deferred.

See Also

[edit]