<?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%2FCode_Map%2FHGEntityTransferModule</id>
	<title>OpenSimulator Internals/Code Map/HGEntityTransferModule - 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%2FCode_Map%2FHGEntityTransferModule"/>
	<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/HGEntityTransferModule&amp;action=history"/>
	<updated>2026-08-04T15:28:08Z</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/Code_Map/HGEntityTransferModule&amp;diff=94&amp;oldid=prev</id>
		<title>Jwbshaw: first</title>
		<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/HGEntityTransferModule&amp;diff=94&amp;oldid=prev"/>
		<updated>2026-07-07T13:20:58Z</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/Code Map/HGEntityTransferModule =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
 OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs&lt;br /&gt;
&lt;br /&gt;
Extends EntityTransferModule. Replaces it when HyperGrid is enabled ([Modules] EntityTransferModule = HGEntityTransferModule). Overrides the key virtual methods to handle cross-grid agent transfer, foreign user logout, appearance restriction, and incoming attachment asset fetching.&lt;br /&gt;
&lt;br /&gt;
Also registers as IUserAgentVerificationModule -- verifies HG client tokens on connection.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
 [EntityTransfer] section&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Key !! Default !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| LevelHGTeleport || 0 || Minimum user level required to HG teleport (local users only)&lt;br /&gt;
|-&lt;br /&gt;
| RestrictAppearanceAbroad || false || If true, enforce exported appearance before HG TP&lt;br /&gt;
|-&lt;br /&gt;
| AccountForAppearance || (empty) || Comma-separated &amp;quot;First Last&amp;quot; account names whose appearance is the allowed export set&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== GetFinalDestination() Override ==&lt;br /&gt;
&lt;br /&gt;
Called during DoTeleportInternal() to resolve the true destination.&lt;br /&gt;
&lt;br /&gt;
# Calls GridService.GetRegionFlags() to check if the destination region has the Hyperlink flag.&lt;br /&gt;
# If Hyperlink: calls GatekeeperServiceConnector.GetHyperlinkRegion() -- HTTP request to the foreign grid&amp;#039;s Gatekeeper service.&lt;br /&gt;
#* Gatekeeper returns the actual destination GridRegion on the foreign grid.&lt;br /&gt;
# If not Hyperlink: returns the region unchanged (same as base class).&lt;br /&gt;
&lt;br /&gt;
This is the step that resolves a local hyperlink stub into a real foreign region descriptor.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== NeedsClosing() Override ==&lt;br /&gt;
&lt;br /&gt;
Returns true (source agent should be fully closed after transfer) if:&lt;br /&gt;
* OutViewRange is true, OR&lt;br /&gt;
* The destination region has the Hyperlink flag or is unknown (flags == -1).&lt;br /&gt;
&lt;br /&gt;
HG teleports always close the source agent regardless of view distance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== CreateAgent() Override ==&lt;br /&gt;
&lt;br /&gt;
Called during DoTeleportInternal() to create the agent at the destination.&lt;br /&gt;
&lt;br /&gt;
# Calls GridService.GetRegionFlags() to check if destination is a Hyperlink region.&lt;br /&gt;
# If Hyperlink (HG teleport):&lt;br /&gt;
#* Checks if local user has sufficient UserLevel (&amp;gt;= LevelHGTeleport). Refuses if not.&lt;br /&gt;
#* Reads HomeURI from agentCircuit.ServiceURLs.&lt;br /&gt;
#* Gets or creates a UserAgentServiceConnector for the home grid.&lt;br /&gt;
#* Calls UserAgentService.LoginAgentToGrid() -- HTTP POST to home grid&amp;#039;s UserAgent service.&lt;br /&gt;
#*: Home grid&amp;#039;s UserAgent service calls the foreign Gatekeeper to create the agent there.&lt;br /&gt;
#* Sets logout = true -- flags that this agent should be logged out of the source grid after transfer.&lt;br /&gt;
#* Fires TriggerTeleportStart on success.&lt;br /&gt;
# If not Hyperlink: calls base.CreateAgent() -- normal SimulationService.CreateAgent().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== AgentHasMovedAway() Override ==&lt;br /&gt;
&lt;br /&gt;
Called after the agent has successfully moved to destination.&lt;br /&gt;
&lt;br /&gt;
# Calls base.AgentHasMovedAway() (currently a no-op in base).&lt;br /&gt;
# If logout == true (HG teleport):&lt;br /&gt;
#* Calls PresenceService.LogoutAgent() -- marks agent offline in source grid&amp;#039;s presence table.&lt;br /&gt;
#* Calls GridUserService.LoggedOut() -- updates source grid&amp;#039;s griduser table with last position.&lt;br /&gt;
&lt;br /&gt;
This is the HG-specific grid logout. The agent is now on the foreign grid and is no longer a presence on the source grid.&lt;br /&gt;
&lt;br /&gt;
; DB writes (source grid, HG teleport only):&lt;br /&gt;
* presence -- UPDATE: Online=0, session cleared&lt;br /&gt;
* griduser -- UPDATE: LastPosition, Logout timestamp&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== ValidateGenericConditions() Override ==&lt;br /&gt;
&lt;br /&gt;
Called before teleport proceeds. For HG teleports with RestrictAppearanceAbroad=true:&lt;br /&gt;
&lt;br /&gt;
# Checks if destination is a Hyperlink region.&lt;br /&gt;
# For local grid users going HG:&lt;br /&gt;
#* Checks each wearable slot against the exported appearance (ExportedAppearance property).&lt;br /&gt;
#* Checks each attachment against the exported attachment list.&lt;br /&gt;
#* Returns false (rejects teleport) if any item is not in the allowed set.&lt;br /&gt;
&lt;br /&gt;
ExportedAppearance: lazy-loaded on first access. Loads appearance for each account in AccountForAppearance from AvatarService, resolves attachment ItemIDs to AssetIDs via InventoryService.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== OnConnectionClosed() Override ==&lt;br /&gt;
&lt;br /&gt;
Called when viewer disconnects.&lt;br /&gt;
&lt;br /&gt;
For local grid users: calls IUserAgentService.LogoutAgent() -- notifies home UserAgent service.&lt;br /&gt;
&lt;br /&gt;
For foreign (HG) users:&lt;br /&gt;
# Gets HomeURI from AgentCircuitData.ServiceURLs.&lt;br /&gt;
# Creates UserAgentServiceConnector for the home grid.&lt;br /&gt;
# Calls security.LogoutAgent() -- HTTP POST to foreign home grid&amp;#039;s UserAgent service.&lt;br /&gt;
# Calls base.OnConnectionClosed() -- handles abort-in-transit case.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== TeleportHome() Override ==&lt;br /&gt;
&lt;br /&gt;
For local grid users: delegates to base.TeleportHome() which uses GridUserService to find home region.&lt;br /&gt;
&lt;br /&gt;
For foreign (HG) users:&lt;br /&gt;
# Gets HomeURI from AgentCircuitData.ServiceURLs.&lt;br /&gt;
# Calls UserAgentService.GetHomeRegion() -- HTTP request to foreign home grid.&lt;br /&gt;
# Constructs a Gatekeeper GridRegion from the HomeURI.&lt;br /&gt;
# Calls DoTeleport() with ViaHome flag.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== HandleIncomingSceneObject() Override ==&lt;br /&gt;
&lt;br /&gt;
Called when an object crosses into this region from another.&lt;br /&gt;
&lt;br /&gt;
For foreign-user attachments arriving via HGLogin (ViaHGLogin flag set):&lt;br /&gt;
# Adds object to scene immediately.&lt;br /&gt;
# Queues an async job on m_incomingSceneObjectEngine (JobEngine, 30s timeout).&lt;br /&gt;
# Job: creates HGUuidGatherer with the foreign AssetServerURI from AgentCircuitData.&lt;br /&gt;
#* Gathers all referenced asset UUIDs from the SOG recursively.&lt;br /&gt;
#* Fetches each asset from the foreign grid&amp;#039;s asset server.&lt;br /&gt;
#* 30-second timeout per gather/fetch step -- removes all jobs for that owner on timeout.&lt;br /&gt;
# After fetch: calls base.HandleIncomingSceneObject().&lt;br /&gt;
&lt;br /&gt;
For non-HGLogin foreign user attachments (already fetched by first local grid region): calls base directly.&lt;br /&gt;
&lt;br /&gt;
For local user attachments: calls base directly.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== HandleIncomingAttachments() Override ==&lt;br /&gt;
&lt;br /&gt;
Same pattern as HandleIncomingSceneObject() but for the attachment list transferred in AgentData during crossing/teleport.&lt;br /&gt;
&lt;br /&gt;
For foreign HGLogin users:&lt;br /&gt;
# Queues async job.&lt;br /&gt;
# HGUuidGatherer fetches all attachment assets from foreign AssetServerURI.&lt;br /&gt;
# On completion: calls base.HandleIncomingAttachments().&lt;br /&gt;
&lt;br /&gt;
Includes sp.IsDeleted check in fetch loop -- aborts if avatar departed during the fetch.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== VerifyClient() ==&lt;br /&gt;
&lt;br /&gt;
IUserAgentVerificationModule implementation. Called by Scene.CheckClient() for HG arrivals.&lt;br /&gt;
&lt;br /&gt;
# Gets HomeURI from AgentCircuitData.&lt;br /&gt;
# Creates UserAgentServiceConnector.&lt;br /&gt;
# Calls security.VerifyClient(SessionID, token) -- HTTP POST to foreign home grid.&lt;br /&gt;
# Returns true/false.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Incoming Attachment Processing ==&lt;br /&gt;
&lt;br /&gt;
m_incomingSceneObjectEngine: JobEngine with 30-second stall timeout. One engine per region. Processes HG attachment asset fetches serially per owner (CommonId = OwnerID).&lt;br /&gt;
&lt;br /&gt;
RemoveIncomingSceneObjectJobs(commonId): drains the queue and reinserts all jobs except those matching the given owner UUID. Used on timeout to cancel stuck fetches.&lt;br /&gt;
&lt;br /&gt;
Stat registered: &amp;quot;HGIncomingAttachmentsWaiting&amp;quot; -- pull stat showing queue depth.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&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 Goes HG]]&lt;/div&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
</feed>