<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FWalkthroughs%2FAvatar_Goes_HG</id>
	<title>OpenSimulator Internals/Walkthroughs/Avatar Goes HG - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FWalkthroughs%2FAvatar_Goes_HG"/>
	<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;action=history"/>
	<updated>2026-08-04T15:37:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;diff=110&amp;oldid=prev</id>
		<title>Jwbshaw: Added material from opensimulator.org wiki</title>
		<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;diff=110&amp;oldid=prev"/>
		<updated>2026-07-07T23:29:59Z</updated>

		<summary type="html">&lt;p&gt;Added material from opensimulator.org wiki&lt;/p&gt;
&lt;a href=&quot;http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;amp;diff=110&amp;amp;oldid=86&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
	<entry>
		<id>http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;diff=86&amp;oldid=prev</id>
		<title>Jwbshaw: first</title>
		<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Walkthroughs/Avatar_Goes_HG&amp;diff=86&amp;oldid=prev"/>
		<updated>2026-07-07T13:11:03Z</updated>

		<summary type="html">&lt;p&gt;first&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= OpenSimulator Internals/Walkthroughs/Avatar Goes HG =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Traces what happens in code, connectors, and database when an avatar HyperGrid teleports from their home grid to a foreign grid, and when they return.&lt;br /&gt;
&lt;br /&gt;
Assumes the home grid runs ROBUST + OpenSim with HGEntityTransferModule enabled.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Part 1: Departing the Home Grid ==&lt;br /&gt;
&lt;br /&gt;
=== 1. HG Destination Resolved ===&lt;br /&gt;
&lt;br /&gt;
 OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs -- GetFinalDestination()&lt;br /&gt;
 OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs&lt;br /&gt;
&lt;br /&gt;
# Avatar clicks a HG link or enters a HG URI (e.g. hg.example.com:8002:RegionName).&lt;br /&gt;
# GridService on source region looks up the destination -- finds a region with RegionFlags.Hyperlink set. This is a local stub entry, not a real region.&lt;br /&gt;
# GetFinalDestination() detects the Hyperlink flag.&lt;br /&gt;
# Calls GatekeeperServiceConnector.GetHyperlinkRegion() -- HTTP POST to the foreign grid&amp;#039;s Gatekeeper service (hg.example.com:8002).&lt;br /&gt;
#* Gatekeeper validates the request and returns a real GridRegion descriptor for the destination on the foreign grid.&lt;br /&gt;
# ValidateGenericConditions() checks appearance restrictions if RestrictAppearanceAbroad=true.&lt;br /&gt;
&lt;br /&gt;
=== 2. Pre-flight at Foreign Gatekeeper ===&lt;br /&gt;
&lt;br /&gt;
 EntityTransferModule -- DoTeleportInternal()&lt;br /&gt;
&lt;br /&gt;
# SimulationService.QueryAccess() -- HTTP POST to destination simulator on foreign grid.&lt;br /&gt;
#* Destination checks ban list, parcel access, agent limit.&lt;br /&gt;
# sp.Appearance.CanTeleport() -- checks outfit compatibility with destination protocol version.&lt;br /&gt;
&lt;br /&gt;
=== 3. Agent Created at Foreign Grid ===&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- CreateAgent() override&lt;br /&gt;
&lt;br /&gt;
# Detects Hyperlink destination.&lt;br /&gt;
# Checks local user&amp;#039;s UserLevel &amp;gt;= LevelHGTeleport. Refuses if insufficient.&lt;br /&gt;
# Gets HomeURI from agentCircuit.ServiceURLs.&lt;br /&gt;
# Creates UserAgentServiceConnector for home grid&amp;#039;s UserAgent service.&lt;br /&gt;
# Calls UserAgentService.LoginAgentToGrid(source, agentCircuit, gatekeeperRegion, finalDestination, false) -- HTTP POST to home grid&amp;#039;s UserAgent service.&lt;br /&gt;
#* Home UserAgent service validates the request.&lt;br /&gt;
#* Home UserAgent service calls foreign Gatekeeper.CreateAgent() -- HTTP POST to foreign gatekeeper.&lt;br /&gt;
#* Foreign Gatekeeper validates, calls foreign destination simulator&amp;#039;s NewUserConnection.&lt;br /&gt;
#* Returns success.&lt;br /&gt;
# Sets logout = true -- this agent will be logged out of home grid.&lt;br /&gt;
# Fires TriggerTeleportStart.&lt;br /&gt;
&lt;br /&gt;
=== 4. Agent State Sent ===&lt;br /&gt;
&lt;br /&gt;
Same as standard teleport (see [[OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions]] steps 5-6):&lt;br /&gt;
&lt;br /&gt;
# sp.IsChildAgent = true set on source.&lt;br /&gt;
# TeleportFinishEvent sent to viewer with foreign destination endpoint and caps URL.&lt;br /&gt;
# AgentData built via sp.CopyTo() -- includes appearance, attachments with script states.&lt;br /&gt;
# SimulationService.UpdateAgent() -- HTTP POST to foreign destination simulator.&lt;br /&gt;
#* Foreign destination&amp;#039;s IncomingUpdateChildAgent() → CopyFrom() fires.&lt;br /&gt;
# UpdateAgent() waits for avatar to become root at destination.&lt;br /&gt;
&lt;br /&gt;
=== 5. Source Grid Logs Out Agent ===&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- AgentHasMovedAway() override&lt;br /&gt;
&lt;br /&gt;
Called after UpdateAgent() returns successfully:&lt;br /&gt;
&lt;br /&gt;
# sp.HasMovedAway() -- sends kill packets for non-HUD attachments, handles parcel visibility.&lt;br /&gt;
# sp.MakeChildAgent() -- source becomes child.&lt;br /&gt;
# sp.closeAllChildAgents() -- closes all neighbour child agents (logout=true path).&lt;br /&gt;
# AgentHasMovedAway() fires:&lt;br /&gt;
#* PresenceService.LogoutAgent(sessionID) -- marks agent offline on home grid.&lt;br /&gt;
#* GridUserService.LoggedOut(userID, ...) -- updates home grid&amp;#039;s griduser with last position.&lt;br /&gt;
# NeedsClosing() returns true for HG (always) -- CloseAgent() called on source after delay.&lt;br /&gt;
&lt;br /&gt;
; DB writes (home grid):&lt;br /&gt;
* presence -- UPDATE: Online=0&lt;br /&gt;
* griduser -- UPDATE: LastPosition, Logout timestamp&lt;br /&gt;
&lt;br /&gt;
=== 6. Avatar Arrives at Foreign Grid ===&lt;br /&gt;
&lt;br /&gt;
Foreign destination&amp;#039;s CompleteMovement() fires when viewer sends CompleteMovementToRegion.&lt;br /&gt;
&lt;br /&gt;
Standard arrival sequence (see [[OpenSimulator Internals/Walkthroughs/Avatar Rez In Region]]) with HG differences:&lt;br /&gt;
&lt;br /&gt;
* TeleportFlags.ViaHGLogin is set -- baked texture validation skipped (AvatarFactory.ValidateBakedTextureCache() not called for HG).&lt;br /&gt;
* Attachments carried in AgentData. HandleIncomingAttachments() called.&lt;br /&gt;
* For HGLogin: HGEntityTransferModule.HandleIncomingAttachments() queues async asset fetch:&lt;br /&gt;
#* HGUuidGatherer walks each attachment SOG, collects all referenced asset UUIDs.&lt;br /&gt;
#* Fetches each asset from home grid&amp;#039;s AssetServerURI (from AgentCircuitData.ServiceURLs).&lt;br /&gt;
#* 30-second timeout per asset fetch. On timeout: cancels all pending jobs for this avatar.&lt;br /&gt;
#* On completion: base.HandleIncomingAttachments() adds SOGs to scene.&lt;br /&gt;
* Foreign grid does NOT write to home grid&amp;#039;s databases. Avatar&amp;#039;s home presence/griduser records are already marked offline (step 5).&lt;br /&gt;
&lt;br /&gt;
; DB writes (foreign grid):&lt;br /&gt;
* None for standard avatar data. Foreign grid may cache fetched assets locally.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Part 2: Returning Home ==&lt;br /&gt;
&lt;br /&gt;
=== 1. TeleportHome Initiated ===&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- TeleportHome()&lt;br /&gt;
&lt;br /&gt;
# Avatar clicks &amp;quot;Teleport Home&amp;quot; or script calls llTeleportAgentHome().&lt;br /&gt;
# HGEntityTransferModule.TeleportHome() detects foreign user (IsLocalGridUser returns false).&lt;br /&gt;
# Gets HomeURI from AgentCircuitData.ServiceURLs.&lt;br /&gt;
# Creates UserAgentServiceConnector for home grid.&lt;br /&gt;
# Calls UserAgentService.GetHomeRegion(agentID) -- HTTP GET to home grid&amp;#039;s UserAgent service.&lt;br /&gt;
#* Home UserAgent reads griduser table for HomeRegionID, HomePosition, HomeLookAt.&lt;br /&gt;
#* Returns GridRegion descriptor for home region.&lt;br /&gt;
# Constructs Gatekeeper GridRegion from HomeURI.&lt;br /&gt;
# Calls DoTeleport() with ViaHome flag.&lt;br /&gt;
&lt;br /&gt;
=== 2. Home Grid Re-entry ===&lt;br /&gt;
&lt;br /&gt;
Same protocol as any HG teleport but in reverse -- foreign grid is now source, home grid is destination.&lt;br /&gt;
&lt;br /&gt;
Home grid&amp;#039;s Gatekeeper receives CreateAgent request. Home grid validates. Home grid&amp;#039;s NewUserConnection() fires. Standard arrival sequence.&lt;br /&gt;
&lt;br /&gt;
On home grid arrival:&lt;br /&gt;
* TeleportFlags.ViaHGLogin is set.&lt;br /&gt;
* Home grid does NOT call PresenceService.LoginAgent() again -- the session was already established on initial login. A new session is established via the Gatekeeper flow.&lt;br /&gt;
* Baked texture validation skipped.&lt;br /&gt;
* Appearance data arrived via AgentData -- if RestrictAppearanceAbroad was enforced, avatar may arrive in restricted appearance.&lt;br /&gt;
&lt;br /&gt;
=== 3. Foreign Grid Logs Out ===&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- AgentHasMovedAway() (foreign grid side)&lt;br /&gt;
 HGEntityTransferModule -- OnConnectionClosed()&lt;br /&gt;
&lt;br /&gt;
# AgentHasMovedAway() with logout=true:&lt;br /&gt;
#* PresenceService.LogoutAgent() on foreign grid (clears foreign presence record if any).&lt;br /&gt;
#* GridUserService.LoggedOut() on foreign grid.&lt;br /&gt;
# OnConnectionClosed() fires when viewer disconnects from foreign grid:&lt;br /&gt;
#* For foreign user: calls UserAgentServiceConnector(homeURI).LogoutAgent() -- HTTP POST to home grid&amp;#039;s UserAgent service notifying of departure.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Part 3: HG Landmark Teleport ==&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- RequestTeleportLandmark()&lt;br /&gt;
&lt;br /&gt;
# Landmark contains Gatekeeper URI + RegionID + position.&lt;br /&gt;
# If gatekeeper is local grid: falls back to normal landmark teleport.&lt;br /&gt;
# If foreign gatekeeper:&lt;br /&gt;
#* DNS-resolves the gatekeeper host.&lt;br /&gt;
#* Calls GatekeeperServiceConnector.GetHyperlinkRegion() -- resolves RegionID to GridRegion on foreign grid.&lt;br /&gt;
#* Calls ValidateGenericConditions() (appearance check).&lt;br /&gt;
#* Calls DoTeleport() -- standard HG teleport from here.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Client Verification ==&lt;br /&gt;
&lt;br /&gt;
 HGEntityTransferModule -- VerifyClient()&lt;br /&gt;
&lt;br /&gt;
Called by Scene.CheckClient() on first HTTP contact from a foreign avatar&amp;#039;s viewer.&lt;br /&gt;
&lt;br /&gt;
# Gets HomeURI.&lt;br /&gt;
# Calls UserAgentServiceConnector(homeURI).VerifyClient(SessionID, token).&lt;br /&gt;
#* Home grid&amp;#039;s UserAgent service confirms the session is valid.&lt;br /&gt;
# Returns false → scene removes circuit and closes agent.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Summary: DB Tables Touched ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Table !! Grid !! Operation !! Step&lt;br /&gt;
|-&lt;br /&gt;
| presence || Home || UPDATE: Online=0 || Source logs out (step 5)&lt;br /&gt;
|-&lt;br /&gt;
| griduser || Home || UPDATE: LastPosition, Logout || Source logs out (step 5)&lt;br /&gt;
|-&lt;br /&gt;
| assets || Foreign || INSERT: fetched attachment assets || Incoming asset fetch (step 6)&lt;br /&gt;
|-&lt;br /&gt;
| presence || Foreign || UPDATE: session cleanup || Return/logout (part 2 step 3)&lt;br /&gt;
|-&lt;br /&gt;
| griduser || Foreign || UPDATE: LastPosition || Return/logout (part 2 step 3)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Key HG-specific Differences from Standard Teleport ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Aspect !! Standard Teleport !! HG Teleport&lt;br /&gt;
|-&lt;br /&gt;
| CreateAgent || SimulationService.CreateAgent() direct || UserAgentService.LoginAgentToGrid() via home grid&lt;br /&gt;
|-&lt;br /&gt;
| logout flag || false || true&lt;br /&gt;
|-&lt;br /&gt;
| Source logs out || No || Yes (PresenceService + GridUserService)&lt;br /&gt;
|-&lt;br /&gt;
| NeedsClosing || Only if OutViewRange || Always&lt;br /&gt;
|-&lt;br /&gt;
| Attachment fetch || Carried in AgentData || Async HGUuidGatherer from foreign AssetServer&lt;br /&gt;
|-&lt;br /&gt;
| Baked texture validation || Yes || No (ViaHGLogin)&lt;br /&gt;
|-&lt;br /&gt;
| OnConnectionClosed || Base handler || Also notifies home UserAgent service&lt;br /&gt;
|-&lt;br /&gt;
| TeleportHome || GridUserService.GetHomeRegion || UserAgentService.GetHomeRegion&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/HGEntityTransferModule]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/EntityTransferModule]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST/GatekeeperService]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST/UserAgentService]]&lt;br /&gt;
* [[OpenSimulator Internals/Connector Architecture/Gatekeeper Connector]]&lt;br /&gt;
* [[OpenSimulator Internals/Connector Architecture/UserAgent Connector]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Rez In Region]]&lt;/div&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
</feed>