<?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%2FEntityTransferModule</id>
	<title>OpenSimulator Internals/Code Map/EntityTransferModule - 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%2FEntityTransferModule"/>
	<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/EntityTransferModule&amp;action=history"/>
	<updated>2026-08-04T15:35:11Z</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/EntityTransferModule&amp;diff=93&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/EntityTransferModule&amp;diff=93&amp;oldid=prev"/>
		<updated>2026-07-07T13:19:54Z</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/EntityTransferModule =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
 OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs&lt;br /&gt;
&lt;br /&gt;
INonSharedRegionModule. Handles all agent movement between regions: teleport (within region and to other regions), region crossing, child agent management, and object crossing. One instance per region.&lt;br /&gt;
&lt;br /&gt;
Registered as IEntityTransferModule. Extended by HGEntityTransferModule for HyperGrid.&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;
| wait_for_callback || true || Source region waits for destination to confirm arrival before closing agent&lt;br /&gt;
|-&lt;br /&gt;
| DisableInterRegionTeleportCancellation || false || If true, tells viewer to disable cancel button&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Event Wiring ==&lt;br /&gt;
&lt;br /&gt;
OnNewClient() hooks per client:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event !! Handler&lt;br /&gt;
|-&lt;br /&gt;
| OnTeleportHomeRequest || TriggerTeleportHome()&lt;br /&gt;
|-&lt;br /&gt;
| OnTeleportLandmarkRequest || RequestTeleportLandmark()&lt;br /&gt;
|-&lt;br /&gt;
| OnTeleportCancel || OnClientCancelTeleport() (if cancellation enabled)&lt;br /&gt;
|-&lt;br /&gt;
| OnConnectionClosed || OnConnectionClosed()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
OnConnectionClosed(): if client IsLoggingOut while in transit, updates transfer state to Aborting.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Transfer State Machine ==&lt;br /&gt;
&lt;br /&gt;
EntityTransferStateMachine tracks per-agent transfer state:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! State !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| (none) || Not in transit&lt;br /&gt;
|-&lt;br /&gt;
| Transferring || Transfer initiated, past point of no clean abort&lt;br /&gt;
|-&lt;br /&gt;
| ReceivedAtDestination || Destination confirmed arrival&lt;br /&gt;
|-&lt;br /&gt;
| CleaningUp || Closing child agents and source agent&lt;br /&gt;
|-&lt;br /&gt;
| Cancelling || Client requested cancel&lt;br /&gt;
|-&lt;br /&gt;
| Aborting || Client disconnected during transfer&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SetInTransit() / ResetFromTransit() bracket the full operation. UpdateInTransit() moves through states. Failed transitions are logged and abort the operation.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Teleport Entry Point ==&lt;br /&gt;
&lt;br /&gt;
 Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)&lt;br /&gt;
&lt;br /&gt;
# Checks permissions (CanTeleport). Adds Godlike flag if grid god.&lt;br /&gt;
# Calls SetInTransit() -- rejects if already in transit.&lt;br /&gt;
# If destination handle matches current region after offset check: calls TeleportAgentWithinRegion().&lt;br /&gt;
# Otherwise: calls TeleportAgentToDifferentRegion().&lt;br /&gt;
# ResetFromTransit() in finally block.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== TeleportAgentWithinRegion() ==&lt;br /&gt;
&lt;br /&gt;
Local teleport within the same region.&lt;br /&gt;
&lt;br /&gt;
# Validates position is within region bounds; substitutes emergency pos (128,128,128) if not.&lt;br /&gt;
# Raises Z to ground height + avatar half-height.&lt;br /&gt;
# Sends TeleportStart to viewer.&lt;br /&gt;
# Sends SendLocalTeleport to viewer.&lt;br /&gt;
# Sets sp.TeleportFlags, rotates avatar, zeros velocity.&lt;br /&gt;
# Calls sp.Teleport(position) -- moves physics actor.&lt;br /&gt;
# Fires CHANGED_TELEPORT script event on all attachment SOGs.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== TeleportAgentToDifferentRegion() ==&lt;br /&gt;
&lt;br /&gt;
# Calls GetTeleportDestinationRegion() -- GridService.GetRegionByPosition() accounting for varregion offsets.&lt;br /&gt;
# Calls GetFinalDestination() (HG hook -- returns same region for normal grid).&lt;br /&gt;
# Calls ValidateGenericConditions() (override point).&lt;br /&gt;
# Calls DoTeleportInternal().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== DoTeleportInternal() ==&lt;br /&gt;
&lt;br /&gt;
Core cross-simulator teleport sequence.&lt;br /&gt;
&lt;br /&gt;
# DNS resolution: finalDestination.ExternalEndPoint.&lt;br /&gt;
# Calls SimulationService.QueryAccess() -- destination region confirms it will accept the agent. Returns reason string on refusal.&lt;br /&gt;
# Checks sp.Appearance.CanTeleport(ctx.OutboundVersion) -- rejects if outfit incompatible with destination protocol version.&lt;br /&gt;
# If avatar sitting: calls sp.StandUp().&lt;br /&gt;
# Sets sp.IsInTransit = true.&lt;br /&gt;
# Sends TeleportStart to viewer.&lt;br /&gt;
# Builds AgentCircuitData for the destination.&lt;br /&gt;
# Determines OutSideViewRange -- whether destination already has a child agent or needs a new one.&lt;br /&gt;
# Selects protocol version: V2 (&amp;gt;= 0.2) or V1 fallback.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== TransferAgent_V2() ==&lt;br /&gt;
&lt;br /&gt;
Current protocol path.&lt;br /&gt;
&lt;br /&gt;
# If OutSideViewRange: removes current region handle from ChildrenCapSeeds.&lt;br /&gt;
# Calls CreateAgent() -- SimulationService.CreateAgent() to destination. Fires TeleportStart event.&lt;br /&gt;
# Checks cancel/abort state.&lt;br /&gt;
# Sets sp.IsChildAgent = true.&lt;br /&gt;
# Sends TeleportFinishEvent to viewer immediately (V2 difference from V1: no prior EnableSimulator/EstablishAgentCommunication).&lt;br /&gt;
# Builds full AgentData via sp.CopyTo() including appearance, animations, attachments, script states.&lt;br /&gt;
# Sets SenderWantsToWaitForRoot = true in AgentData.&lt;br /&gt;
# Calls UpdateAgent() -- SimulationService.UpdateAgent() sends full agent state to destination. Blocks until destination&amp;#039;s CompleteMovement() fires and returns.&lt;br /&gt;
# On UpdateAgent success: calls sp.HasMovedAway(), sp.MakeChildAgent(), CloseChildAgents().&lt;br /&gt;
# If NeedsClosing (OutSideViewRange): waits up to 15 seconds for sp.IsInTransit to clear, then calls m_scene.CloseAgent().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== TransferAgent_V1() ==&lt;br /&gt;
&lt;br /&gt;
Legacy protocol path (destination protocol &amp;lt; 0.2).&lt;br /&gt;
&lt;br /&gt;
# Calls CreateAgent().&lt;br /&gt;
# If OutSideViewRange: sends EnableSimulator + EstablishAgentCommunication via event queue, then sleeps 200ms.&lt;br /&gt;
# Sends full AgentData via UpdateAgent().&lt;br /&gt;
# Sends TeleportFinishEvent.&lt;br /&gt;
# Waits for WaitForAgentArrivedAtDestination() callback -- blocks up to 10 seconds.&lt;br /&gt;
# On success: CloseChildAgents(), MakeChildAgent(), CloseAgent() after 2-second sleep (viewer compatibility).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Region Crossing ==&lt;br /&gt;
&lt;br /&gt;
Cross(ScenePresence, isFlying):&lt;br /&gt;
* Fires async via WorkManager.RunInThreadPool.&lt;br /&gt;
* Calls CrossAsync() → CrossAgentToNewRegionAsync() → CrossAgentIntoNewRegionMain().&lt;br /&gt;
&lt;br /&gt;
CrossAgentIntoNewRegionMain():&lt;br /&gt;
# Calls sp.CopyTo(cAgent, isCrossUpdate=true) -- full agent state including cross flags.&lt;br /&gt;
# Sets position to projected crossing position.&lt;br /&gt;
# Calls SimulationService.UpdateAgent() -- sends state to destination. Destination&amp;#039;s IncomingUpdateChildAgent() fires, sets m_originRegionID.&lt;br /&gt;
# On success: sets sp.IsChildAgent = true, sends CrossRegion event queue message to viewer.&lt;br /&gt;
# CloseChildAgents() for out-of-range neighbours.&lt;br /&gt;
# Calls sp.HasMovedAway(), sp.MakeChildAgent().&lt;br /&gt;
&lt;br /&gt;
CrossAsync() detects crossing by projecting position + velocity * 0.2s and calling GetDestination() → GridService.GetRegionByPosition().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Child Agent Management ==&lt;br /&gt;
&lt;br /&gt;
EnableChildAgents(ScenePresence sp):&lt;br /&gt;
* Computes neighbours within RegionViewDistance via RegionsInSPView().&lt;br /&gt;
* For new neighbours: builds AgentCircuitData, calls CreateAgent() + EnableSimulator + EstablishAgentCommunication.&lt;br /&gt;
* For regions no longer in view: calls sp.CloseChildAgents().&lt;br /&gt;
* Updates KnownRegions and cap seeds.&lt;br /&gt;
* Sends AgentPosition updates to existing known neighbours.&lt;br /&gt;
* Neighbour list cached for 30 seconds.&lt;br /&gt;
&lt;br /&gt;
EnableChildAgent(sp, region): single-region version, used when a new neighbour comes online.&lt;br /&gt;
&lt;br /&gt;
CloseOldChildAgents(sp): called from SendInitialData() on login. Closes any child agents not in current view range.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Failure Handling ==&lt;br /&gt;
&lt;br /&gt;
Fail():&lt;br /&gt;
* Calls CleanupFailedInterRegionTeleport() -- sets IsChildAgent=false, ReInstantiateScripts(), calls SimulationService.CloseAgent() on destination.&lt;br /&gt;
* Sends TeleportFailed to viewer.&lt;br /&gt;
* Fires TriggerTeleportFail event.&lt;br /&gt;
&lt;br /&gt;
BannedRegionCache: ExpiringCacheOS keyed by region handle → Dictionary&amp;lt;UUID, expiry&amp;gt;. Regions that refuse QueryAccess are cached for 60 seconds to avoid hammering.&lt;br /&gt;
&lt;br /&gt;
NotFoundLocationCache: Caches region handle positions that returned null from GridService for 30 seconds.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Key Virtual Methods (HG Override Points) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| GetFinalDestination() || Returns destination region (HG overrides to resolve HG address)&lt;br /&gt;
|-&lt;br /&gt;
| CreateAgent() || Calls SimulationService.CreateAgent() (HG overrides to set logout flag)&lt;br /&gt;
|-&lt;br /&gt;
| UpdateAgent() || Calls SimulationService.UpdateAgent()&lt;br /&gt;
|-&lt;br /&gt;
| AgentHasMovedAway() || Hook after agent departs (HG deletes attachments from scene)&lt;br /&gt;
|-&lt;br /&gt;
| NeedsClosing() || Whether to close source agent (HG uses different logic)&lt;br /&gt;
|-&lt;br /&gt;
| ValidateGenericConditions() || Additional pre-flight checks (base returns true)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Object Crossing ==&lt;br /&gt;
&lt;br /&gt;
CrossPrimGroupIntoNewRegion():&lt;br /&gt;
* Calls SimulationService.CreateObject() on destination.&lt;br /&gt;
* On success: calls scene.DeleteSceneObject() on source.&lt;br /&gt;
&lt;br /&gt;
GetObjectDestination(): projects object position into world coordinates, calls GridService.GetRegionByPosition().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Statistics ==&lt;br /&gt;
&lt;br /&gt;
Four stats registered per region under &amp;quot;entitytransfer&amp;quot; category:&lt;br /&gt;
* InterRegionTeleportAttempts&lt;br /&gt;
* InterRegionTeleportAborts (simultaneous logout)&lt;br /&gt;
* InterRegionTeleportCancels (client cancel)&lt;br /&gt;
* InterRegionTeleportFailures (network/server problems)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ScenePresence]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/Scene]]&lt;br /&gt;
* [[OpenSimulator Internals/Connector Architecture/Simulation Connector]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Logs Out]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Transfer Between Regions]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Goes HG]]&lt;/div&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
</feed>