2007-12-27 21:41:48 +00:00
/ *
2008-03-18 05:16:43 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2007-12-11 01:26:06 +00:00
using System ;
2007-11-04 14:34:45 +00:00
using System.Collections.Generic ;
using System.Net ;
2008-04-21 07:09:17 +00:00
using System.Reflection ;
2008-05-01 14:45:56 +00:00
using System.Threading ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
2008-09-27 23:06:28 +00:00
using OpenMetaverse.StructuredData ;
2008-04-21 07:09:17 +00:00
using log4net ;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework ;
2009-05-23 05:44:18 +00:00
using OpenSim.Framework.Client ;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework.Communications ;
2009-02-12 23:23:44 +00:00
using OpenSim.Framework.Communications.Cache ;
2009-06-18 14:33:35 +00:00
using OpenSim.Framework.Capabilities ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Interfaces ;
2009-06-14 15:35:09 +00:00
using OpenSim.Services.Interfaces ;
2008-11-19 06:25:34 +00:00
using OSD = OpenMetaverse . StructuredData . OSD ;
2007-11-04 14:34:45 +00:00
2009-02-06 16:55:34 +00:00
namespace OpenSim.Region.Framework.Scenes
2007-11-04 14:34:45 +00:00
{
2008-09-06 07:52:41 +00:00
public delegate void KiPrimitiveDelegate ( uint localID ) ;
2007-11-27 15:44:39 +00:00
2008-09-06 07:52:41 +00:00
public delegate void RemoveKnownRegionsFromAvatarList ( UUID avatarID , List < ulong > regionlst ) ;
2008-02-20 01:17:21 +00:00
2009-08-15 01:19:04 +00:00
/// <summary>
/// Class that Region communications runs through
/// </summary>
2007-11-04 14:34:45 +00:00
public class SceneCommunicationService //one instance per region
{
2008-04-21 07:09:17 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-02-05 19:44:27 +00:00
2007-11-04 14:34:45 +00:00
protected CommunicationsManager m_commsProvider ;
2008-12-29 22:22:05 +00:00
protected IInterregionCommsOut m_interregionCommsOut ;
2007-11-04 14:34:45 +00:00
protected RegionInfo m_regionInfo ;
protected RegionCommsListener regionCommsHost ;
2009-01-01 19:42:24 +00:00
protected List < UUID > m_agentsInTransit ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// An agent is crossing into this region
/// </summary>
2007-11-04 14:34:45 +00:00
public event AgentCrossing OnAvatarCrossingIntoRegion ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// A user will arrive shortly, set up appropriate credentials so it can connect
/// </summary>
2007-11-04 14:34:45 +00:00
public event ExpectUserDelegate OnExpectUser ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// A Prim will arrive shortly
/// </summary>
2008-02-11 01:43:54 +00:00
public event ExpectPrimDelegate OnExpectPrim ;
2007-11-05 13:58:44 +00:00
public event CloseAgentConnection OnCloseAgentConnection ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// A new prim has arrived
/// </summary>
2007-11-21 02:17:24 +00:00
public event PrimCrossing OnPrimCrossingIntoRegion ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// A New Region is up and available
/// </summary>
2007-11-26 05:02:18 +00:00
public event RegionUp OnRegionUp ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// We have a child agent for this avatar and we're getting a status update about it
/// </summary>
2007-12-10 00:46:56 +00:00
public event ChildAgentUpdate OnChildAgentUpdate ;
2008-12-20 18:15:02 +00:00
//public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
2009-08-15 01:19:04 +00:00
/// <summary>
/// Time to log one of our users off. Grid Service sends this mostly
/// </summary>
2008-05-31 12:18:29 +00:00
public event LogOffUser OnLogOffUser ;
2009-08-15 01:19:04 +00:00
/// <summary>
/// A region wants land data from us!
/// </summary>
2008-08-16 19:20:14 +00:00
public event GetLandData OnGetLandData ;
2008-08-18 00:39:10 +00:00
2008-05-01 18:04:42 +00:00
private AgentCrossing handlerAvatarCrossingIntoRegion = null ; // OnAvatarCrossingIntoRegion;
private ExpectUserDelegate handlerExpectUser = null ; // OnExpectUser;
private ExpectPrimDelegate handlerExpectPrim = null ; // OnExpectPrim;
private CloseAgentConnection handlerCloseAgentConnection = null ; // OnCloseAgentConnection;
private PrimCrossing handlerPrimCrossingIntoRegion = null ; // OnPrimCrossingIntoRegion;
private RegionUp handlerRegionUp = null ; // OnRegionUp;
private ChildAgentUpdate handlerChildAgentUpdate = null ; // OnChildAgentUpdate;
2008-12-17 18:42:23 +00:00
//private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
2008-05-31 12:18:29 +00:00
private LogOffUser handlerLogOffUser = null ;
2008-08-18 00:39:10 +00:00
private GetLandData handlerGetLandData = null ; // OnGetLandData
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
public KiPrimitiveDelegate KiPrimitive ;
2008-05-01 18:04:42 +00:00
public SceneCommunicationService ( CommunicationsManager commsMan )
{
m_commsProvider = commsMan ;
2009-01-01 19:42:24 +00:00
m_agentsInTransit = new List < UUID > ( ) ;
2008-05-01 18:04:42 +00:00
}
2008-05-12 16:57:56 +00:00
/// <summary>
/// Register a region with the grid
/// </summary>
/// <param name="regionInfos"></param>
/// <exception cref="System.Exception">Thrown if region registration fails.</exception>
2008-12-29 22:22:05 +00:00
public void RegisterRegion ( IInterregionCommsOut comms_out , RegionInfo regionInfos )
2007-11-04 14:34:45 +00:00
{
2008-12-29 22:22:05 +00:00
m_interregionCommsOut = comms_out ;
2007-11-04 14:34:45 +00:00
m_regionInfo = regionInfos ;
2008-10-31 18:39:51 +00:00
m_commsProvider . GridService . gdebugRegionName = regionInfos . RegionName ;
2007-11-04 14:34:45 +00:00
regionCommsHost = m_commsProvider . GridService . RegisterRegion ( m_regionInfo ) ;
2007-11-27 13:46:52 +00:00
2007-11-04 14:34:45 +00:00
if ( regionCommsHost ! = null )
{
2008-02-05 19:44:27 +00:00
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
2007-11-27 13:46:52 +00:00
2008-10-31 18:39:51 +00:00
regionCommsHost . debugRegionName = regionInfos . RegionName ;
2008-02-11 01:43:54 +00:00
regionCommsHost . OnExpectPrim + = IncomingPrimCrossing ;
2007-11-04 14:34:45 +00:00
regionCommsHost . OnExpectUser + = NewUserConnection ;
regionCommsHost . OnAvatarCrossingIntoRegion + = AgentCrossing ;
2007-11-05 13:58:44 +00:00
regionCommsHost . OnCloseAgentConnection + = CloseConnection ;
2007-11-26 05:02:18 +00:00
regionCommsHost . OnRegionUp + = newRegionUp ;
2008-05-16 01:22:11 +00:00
regionCommsHost . OnChildAgentUpdate + = ChildAgentUpdate ;
2008-05-31 12:18:29 +00:00
regionCommsHost . OnLogOffUser + = GridLogOffUser ;
2008-08-16 19:20:14 +00:00
regionCommsHost . OnGetLandData + = FetchLandData ;
2007-11-27 13:46:52 +00:00
}
else
{
2008-02-05 19:44:27 +00:00
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
2007-11-04 14:34:45 +00:00
}
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// Returns a region with the name closest to string provided
/// </summary>
/// <param name="name">Partial Region Name for matching</param>
/// <returns>Region Information for the region</returns>
2008-05-29 13:55:02 +00:00
public RegionInfo RequestClosestRegion ( string name )
{
return m_commsProvider . GridService . RequestClosestRegion ( name ) ;
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// This region is shutting down, de-register all events!
/// De-Register region from Grid!
/// </summary>
2007-11-04 14:34:45 +00:00
public void Close ( )
{
2007-11-26 05:02:18 +00:00
if ( regionCommsHost ! = null )
{
2008-05-31 12:18:29 +00:00
regionCommsHost . OnLogOffUser - = GridLogOffUser ;
2007-12-10 00:46:56 +00:00
regionCommsHost . OnChildAgentUpdate - = ChildAgentUpdate ;
2007-11-26 05:02:18 +00:00
regionCommsHost . OnRegionUp - = newRegionUp ;
regionCommsHost . OnExpectUser - = NewUserConnection ;
2008-02-11 01:43:54 +00:00
regionCommsHost . OnExpectPrim - = IncomingPrimCrossing ;
2007-11-26 05:02:18 +00:00
regionCommsHost . OnAvatarCrossingIntoRegion - = AgentCrossing ;
regionCommsHost . OnCloseAgentConnection - = CloseConnection ;
2008-08-16 19:20:14 +00:00
regionCommsHost . OnGetLandData - = FetchLandData ;
2008-09-21 16:58:14 +00:00
try
{
m_commsProvider . GridService . DeregisterRegion ( m_regionInfo ) ;
}
catch ( Exception e )
{
m_log . ErrorFormat (
"[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing" ,
m_regionInfo . RegionName , e ) ;
}
2007-11-26 05:02:18 +00:00
regionCommsHost = null ;
}
2007-11-04 14:34:45 +00:00
}
2008-05-01 18:04:42 +00:00
#region CommsManager Event handlers
/// <summary>
2009-08-15 01:19:04 +00:00
/// A New User will arrive shortly, Informs the scene that there's a new user on the way
2008-05-01 18:04:42 +00:00
/// </summary>
2009-08-15 01:19:04 +00:00
/// <param name="agent">Data we need to ensure that the agent can connect</param>
2008-05-01 18:04:42 +00:00
///
2008-11-12 19:12:33 +00:00
protected void NewUserConnection ( AgentCircuitData agent )
2008-05-01 18:04:42 +00:00
{
handlerExpectUser = OnExpectUser ;
if ( handlerExpectUser ! = null )
{
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
2008-11-12 19:12:33 +00:00
handlerExpectUser ( agent ) ;
2008-05-01 18:04:42 +00:00
}
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// The Grid has requested us to log-off the user
/// </summary>
/// <param name="AgentID">Unique ID of agent to log-off</param>
/// <param name="RegionSecret">The secret string that the region establishes with the grid when registering</param>
/// <param name="message">The message to send to the user that tells them why they were logged off</param>
2008-11-12 19:12:33 +00:00
protected void GridLogOffUser ( UUID AgentID , UUID RegionSecret , string message )
2008-05-31 12:18:29 +00:00
{
handlerLogOffUser = OnLogOffUser ;
if ( handlerLogOffUser ! = null )
{
2008-11-12 19:12:33 +00:00
handlerLogOffUser ( AgentID , RegionSecret , message ) ;
2008-05-31 12:18:29 +00:00
}
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// A New Region is now available. Inform the scene that there is a new region available.
/// </summary>
/// <param name="region">Information about the new region that is available</param>
/// <returns>True if the event was handled</returns>
2008-05-01 18:04:42 +00:00
protected bool newRegionUp ( RegionInfo region )
{
handlerRegionUp = OnRegionUp ;
if ( handlerRegionUp ! = null )
{
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
handlerRegionUp ( region ) ;
}
return true ;
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// Inform the scene that we've got an update about a child agent that we have
/// </summary>
/// <param name="cAgentData"></param>
/// <returns></returns>
2008-11-12 19:12:33 +00:00
protected bool ChildAgentUpdate ( ChildAgentDataUpdate cAgentData )
2008-05-01 18:04:42 +00:00
{
handlerChildAgentUpdate = OnChildAgentUpdate ;
if ( handlerChildAgentUpdate ! = null )
2008-11-12 19:12:33 +00:00
handlerChildAgentUpdate ( cAgentData ) ;
2008-05-01 18:04:42 +00:00
return true ;
}
2009-08-15 01:19:04 +00:00
2008-11-12 19:12:33 +00:00
protected void AgentCrossing ( UUID agentID , Vector3 position , bool isFlying )
2008-05-01 18:04:42 +00:00
{
handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion ;
if ( handlerAvatarCrossingIntoRegion ! = null )
{
2008-11-12 19:12:33 +00:00
handlerAvatarCrossingIntoRegion ( agentID , position , isFlying ) ;
2008-05-01 18:04:42 +00:00
}
}
2009-08-15 01:19:04 +00:00
/// <summary>
/// We have a new prim from a neighbor
/// </summary>
/// <param name="primID">unique ID for the primative</param>
/// <param name="objXMLData">XML2 encoded data of the primative</param>
/// <param name="XMLMethod">An Int that represents the version of the XMLMethod</param>
/// <returns>True if the prim was accepted, false if it was not</returns>
2008-11-12 19:12:33 +00:00
protected bool IncomingPrimCrossing ( UUID primID , String objXMLData , int XMLMethod )
2008-05-01 18:04:42 +00:00
{
handlerExpectPrim = OnExpectPrim ;
if ( handlerExpectPrim ! = null )
{
2008-11-12 19:12:33 +00:00
return handlerExpectPrim ( primID , objXMLData , XMLMethod ) ;
2008-05-01 18:04:42 +00:00
}
else
{
return false ;
}
}
2008-11-12 19:12:33 +00:00
protected void PrimCrossing ( UUID primID , Vector3 position , bool isPhysical )
2008-05-01 18:04:42 +00:00
{
handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion ;
if ( handlerPrimCrossingIntoRegion ! = null )
{
2008-11-12 19:12:33 +00:00
handlerPrimCrossingIntoRegion ( primID , position , isPhysical ) ;
2008-05-01 18:04:42 +00:00
}
}
2008-11-12 19:12:33 +00:00
protected bool CloseConnection ( UUID agentID )
2008-05-01 18:04:42 +00:00
{
2008-11-12 19:12:33 +00:00
m_log . Debug ( "[INTERREGION]: Incoming Agent Close Request for agent: " + agentID ) ;
2008-11-30 23:36:56 +00:00
2008-05-01 18:04:42 +00:00
handlerCloseAgentConnection = OnCloseAgentConnection ;
if ( handlerCloseAgentConnection ! = null )
{
2008-11-12 19:12:33 +00:00
return handlerCloseAgentConnection ( agentID ) ;
2008-05-01 18:04:42 +00:00
}
2008-11-12 19:12:33 +00:00
2008-05-01 18:04:42 +00:00
return false ;
}
2008-08-16 19:20:14 +00:00
protected LandData FetchLandData ( uint x , uint y )
{
handlerGetLandData = OnGetLandData ;
if ( handlerGetLandData ! = null )
{
return handlerGetLandData ( x , y ) ;
}
return null ;
}
2008-08-18 00:39:10 +00:00
2008-05-01 18:04:42 +00:00
# endregion
#region Inform Client of Neighbours
private delegate void InformClientOfNeighbourDelegate (
2008-12-15 16:23:34 +00:00
ScenePresence avatar , AgentCircuitData a , SimpleRegionInfo reg , IPEndPoint endPoint , bool newAgent ) ;
2008-05-01 18:04:42 +00:00
private void InformClientOfNeighbourCompleted ( IAsyncResult iar )
{
InformClientOfNeighbourDelegate icon = ( InformClientOfNeighbourDelegate ) iar . AsyncState ;
icon . EndInvoke ( iar ) ;
}
/// <summary>
2008-11-14 21:06:40 +00:00
/// Async component for informing client of which neighbours exist
2008-05-01 18:04:42 +00:00
/// </summary>
/// <remarks>
2009-03-17 21:20:58 +00:00
/// This needs to run asynchronously, as a network timeout may block the thread for a long while
2008-05-01 18:04:42 +00:00
/// </remarks>
/// <param name="remoteClient"></param>
/// <param name="a"></param>
/// <param name="regionHandle"></param>
/// <param name="endPoint"></param>
2008-12-14 02:17:12 +00:00
private void InformClientOfNeighbourAsync ( ScenePresence avatar , AgentCircuitData a , SimpleRegionInfo reg ,
2008-12-15 16:23:34 +00:00
IPEndPoint endPoint , bool newAgent )
2008-05-01 18:04:42 +00:00
{
2008-12-15 16:23:34 +00:00
// Let's wait just a little to give time to originating regions to catch up with closing child agents
// after a cross here
2008-12-18 19:45:55 +00:00
Thread . Sleep ( 500 ) ;
2008-12-15 16:23:34 +00:00
2008-12-14 02:17:12 +00:00
uint x , y ;
Utils . LongToUInts ( reg . RegionHandle , out x , out y ) ;
x = x / Constants . RegionSize ;
y = y / Constants . RegionSize ;
m_log . Info ( "[INTERGRID]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint . ToString ( ) + ")" ) ;
string capsPath = "http://" + reg . ExternalHostName + ":" + reg . HttpPort
+ "/CAPS/" + a . CapsPath + "0000/" ;
2009-05-05 16:17:52 +00:00
string reason = String . Empty ;
2009-01-03 07:05:33 +00:00
//bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
2009-09-07 16:57:30 +00:00
2009-05-05 16:17:52 +00:00
bool regionAccepted = m_interregionCommsOut . SendCreateChildAgent ( reg . RegionHandle , a , out reason ) ;
2008-05-01 18:04:42 +00:00
2008-12-15 16:23:34 +00:00
if ( regionAccepted & & newAgent )
2008-05-01 18:04:42 +00:00
{
2008-09-27 23:06:28 +00:00
IEventQueue eq = avatar . Scene . RequestModuleInterface < IEventQueue > ( ) ;
if ( eq ! = null )
{
2009-05-23 05:44:18 +00:00
#region IP Translation for NAT
IClientIPEndpoint ipepClient ;
2009-05-31 18:35:00 +00:00
if ( avatar . ClientView . TryGet ( out ipepClient ) )
2009-05-23 05:44:18 +00:00
{
endPoint . Address = NetworkUtil . GetIPFor ( ipepClient . EndPoint , endPoint . Address ) ;
}
# endregion
2009-02-06 16:55:34 +00:00
eq . EnableSimulator ( reg . RegionHandle , endPoint , avatar . UUID ) ;
eq . EstablishAgentCommunication ( avatar . UUID , endPoint , capsPath ) ;
2009-09-07 16:57:30 +00:00
m_log . DebugFormat ( "[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}" ,
2009-02-06 16:55:34 +00:00
capsPath , avatar . UUID , avatar . Scene . RegionInfo . RegionName ) ;
2008-09-27 23:06:28 +00:00
}
else
{
2008-12-14 02:17:12 +00:00
avatar . ControllingClient . InformClientOfNeighbour ( reg . RegionHandle , endPoint ) ;
2008-09-27 23:06:28 +00:00
// TODO: make Event Queue disablable!
}
2008-12-14 02:17:12 +00:00
m_log . Info ( "[INTERGRID]: Completed inform client about neighbour " + endPoint . ToString ( ) ) ;
2009-09-07 16:57:30 +00:00
2008-05-01 18:04:42 +00:00
}
2009-09-07 16:57:30 +00:00
2008-05-01 18:04:42 +00:00
}
public void RequestNeighbors ( RegionInfo region )
{
2008-06-27 19:57:06 +00:00
// List<SimpleRegionInfo> neighbours =
m_commsProvider . GridService . RequestNeighbours ( m_regionInfo . RegionLocX , m_regionInfo . RegionLocY ) ;
2008-05-01 18:04:42 +00:00
//IPEndPoint blah = new IPEndPoint();
//blah.Address = region.RemotingAddress;
//blah.Port = region.RemotingPort;
}
2009-09-07 01:26:59 +00:00
public List < SimpleRegionInfo > RequestNeighbors ( Scene pScene , uint pRegionLocX , uint pRegionLocY )
{
Border [ ] northBorders = pScene . NorthBorders . ToArray ( ) ;
Border [ ] southBorders = pScene . SouthBorders . ToArray ( ) ;
Border [ ] eastBorders = pScene . EastBorders . ToArray ( ) ;
Border [ ] westBorders = pScene . WestBorders . ToArray ( ) ;
// Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement.
if ( northBorders . Length < = 1 & & southBorders . Length < = 1 & & eastBorders . Length < = 1 & & westBorders . Length < = 1 )
{
return m_commsProvider . GridService . RequestNeighbours ( pRegionLocX , pRegionLocY ) ;
}
else
{
2009-09-07 16:57:30 +00:00
Vector2 extent = Vector2 . Zero ;
for ( int i = 0 ; i < eastBorders . Length ; i + + )
{
extent . X = ( eastBorders [ i ] . BorderLine . Z > extent . X ) ? eastBorders [ i ] . BorderLine . Z : extent . X ;
}
for ( int i = 0 ; i < northBorders . Length ; i + + )
{
extent . Y = ( northBorders [ i ] . BorderLine . Z > extent . Y ) ? northBorders [ i ] . BorderLine . Z : extent . Y ;
}
List < SimpleRegionInfo > neighbourList = new List < SimpleRegionInfo > ( ) ;
// Loss of fraction on purpose
extent . X = ( ( int ) extent . X / ( int ) Constants . RegionSize ) + 1 ;
extent . Y = ( ( int ) extent . Y / ( int ) Constants . RegionSize ) + 1 ;
int startX = ( int ) pRegionLocX - 1 ;
int startY = ( int ) pRegionLocY - 1 ;
int endX = ( int ) pRegionLocX + ( int ) extent . X + 1 ;
int endY = ( int ) pRegionLocY + ( int ) extent . Y + 1 ;
for ( int i = startX ; i < endX ; i + + )
{
for ( int j = startY ; j < endY ; j + + )
{
// Skip CurrentRegion
if ( i = = ( int ) pRegionLocX & & j = = ( int ) pRegionLocY )
continue ;
ulong regionHandle = Util . UIntsToLong ( ( uint ) ( i * Constants . RegionSize ) ,
( uint ) ( j * Constants . RegionSize ) ) ;
RegionInfo neighborreg = m_commsProvider . GridService . RequestNeighbourInfo ( regionHandle ) ;
if ( neighborreg ! = null )
{
neighbourList . Add ( neighborreg ) ;
}
}
}
return neighbourList ;
//SimpleRegionInfo regionData = m_commsProvider.GridService.RequestNeighbourInfo()
//return m_commsProvider.GridService.RequestNeighbours(pRegionLocX, pRegionLocY);
2009-09-07 01:26:59 +00:00
}
}
2008-05-01 18:04:42 +00:00
/// <summary>
/// This informs all neighboring regions about agent "avatar".
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary>
public void EnableNeighbourChildAgents ( ScenePresence avatar , List < RegionInfo > lstneighbours )
{
List < SimpleRegionInfo > neighbours = new List < SimpleRegionInfo > ( ) ;
//m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
for ( int i = 0 ; i < lstneighbours . Count ; i + + )
{
// We don't want to keep sending to regions that consistently fail on comms.
if ( ! ( lstneighbours [ i ] . commFailTF ) )
{
neighbours . Add ( new SimpleRegionInfo ( lstneighbours [ i ] ) ) ;
}
}
// we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
// So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
2009-08-01 14:26:00 +00:00
if ( m_regionInfo ! = null )
{
neighbours =
2009-09-07 01:26:59 +00:00
RequestNeighbors ( avatar . Scene , m_regionInfo . RegionLocX , m_regionInfo . RegionLocY ) ;
2009-08-01 14:26:00 +00:00
}
else
{
m_log . Debug ( "[ENABLENEIGHBOURCHILDAGENTS]: m_regionInfo was null in EnableNeighbourChildAgents, is this a NPC?" ) ;
}
2008-05-01 18:04:42 +00:00
2008-12-14 02:17:12 +00:00
/// We need to find the difference between the new regions where there are no child agents
/// and the regions where there are already child agents. We only send notification to the former.
List < ulong > neighbourHandles = NeighbourHandles ( neighbours ) ; // on this region
neighbourHandles . Add ( avatar . Scene . RegionInfo . RegionHandle ) ; // add this region too
2009-08-01 14:26:00 +00:00
List < ulong > previousRegionNeighbourHandles ;
if ( avatar . Scene . CapsModule ! = null )
{
previousRegionNeighbourHandles =
new List < ulong > ( avatar . Scene . CapsModule . GetChildrenSeeds ( avatar . UUID ) . Keys ) ;
}
else
{
previousRegionNeighbourHandles = new List < ulong > ( ) ;
}
2008-12-14 02:17:12 +00:00
List < ulong > newRegions = NewNeighbours ( neighbourHandles , previousRegionNeighbourHandles ) ;
List < ulong > oldRegions = OldNeighbours ( neighbourHandles , previousRegionNeighbourHandles ) ;
//Dump("Current Neighbors", neighbourHandles);
//Dump("Previous Neighbours", previousRegionNeighbourHandles);
//Dump("New Neighbours", newRegions);
//Dump("Old Neighbours", oldRegions);
/// Update the scene presence's known regions here on this region
avatar . DropOldNeighbours ( oldRegions ) ;
/// Collect as many seeds as possible
2009-08-01 14:26:00 +00:00
Dictionary < ulong , string > seeds ;
if ( avatar . Scene . CapsModule ! = null )
seeds
= new Dictionary < ulong , string > ( avatar . Scene . CapsModule . GetChildrenSeeds ( avatar . UUID ) ) ;
else
seeds = new Dictionary < ulong , string > ( ) ;
2009-01-21 21:14:17 +00:00
2009-02-22 20:52:55 +00:00
//m_log.Debug(" !!! No. of seeds: " + seeds.Count);
2008-12-14 02:17:12 +00:00
if ( ! seeds . ContainsKey ( avatar . Scene . RegionInfo . RegionHandle ) )
seeds . Add ( avatar . Scene . RegionInfo . RegionHandle , avatar . ControllingClient . RequestClientInfo ( ) . CapsPath ) ;
/// Create the necessary child agents
List < AgentCircuitData > cagents = new List < AgentCircuitData > ( ) ;
foreach ( SimpleRegionInfo neighbour in neighbours )
2008-05-01 18:04:42 +00:00
{
2008-12-15 16:23:34 +00:00
if ( neighbour . RegionHandle ! = avatar . Scene . RegionInfo . RegionHandle )
2008-05-01 18:04:42 +00:00
{
2008-12-15 16:23:34 +00:00
AgentCircuitData agent = avatar . ControllingClient . RequestClientInfo ( ) ;
agent . BaseFolder = UUID . Zero ;
agent . InventoryFolder = UUID . Zero ;
agent . startpos = new Vector3 ( 128 , 128 , 70 ) ;
agent . child = true ;
if ( newRegions . Contains ( neighbour . RegionHandle ) )
{
2009-01-06 18:26:27 +00:00
agent . CapsPath = CapsUtil . GetRandomCapsObjectPath ( ) ;
2008-12-15 16:23:34 +00:00
avatar . AddNeighbourRegion ( neighbour . RegionHandle , agent . CapsPath ) ;
seeds . Add ( neighbour . RegionHandle , agent . CapsPath ) ;
}
else
2009-01-21 21:14:17 +00:00
agent . CapsPath = avatar . Scene . CapsModule . GetChildSeed ( avatar . UUID , neighbour . RegionHandle ) ;
2008-12-15 16:23:34 +00:00
cagents . Add ( agent ) ;
}
2008-12-14 02:17:12 +00:00
}
2008-05-16 01:22:11 +00:00
2008-12-14 02:17:12 +00:00
/// Update all child agent with everyone's seeds
foreach ( AgentCircuitData a in cagents )
{
a . ChildrenCapSeeds = new Dictionary < ulong , string > ( seeds ) ;
}
2009-08-01 14:26:00 +00:00
if ( avatar . Scene . CapsModule ! = null )
{
// These two are the same thing!
avatar . Scene . CapsModule . SetChildrenSeed ( avatar . UUID , seeds ) ;
}
2008-12-14 02:17:12 +00:00
avatar . KnownRegions = seeds ;
//avatar.Scene.DumpChildrenSeeds(avatar.UUID);
//avatar.DumpKnownRegions();
2008-12-15 16:23:34 +00:00
bool newAgent = false ;
2008-12-14 02:17:12 +00:00
int count = 0 ;
foreach ( SimpleRegionInfo neighbour in neighbours )
{
// Don't do it if there's already an agent in that region
if ( newRegions . Contains ( neighbour . RegionHandle ) )
2008-12-15 16:23:34 +00:00
newAgent = true ;
else
newAgent = false ;
if ( neighbour . RegionHandle ! = avatar . Scene . RegionInfo . RegionHandle )
2008-12-14 02:17:12 +00:00
{
InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync ;
2008-05-01 18:04:42 +00:00
try
{
2008-12-15 16:23:34 +00:00
d . BeginInvoke ( avatar , cagents [ count ] , neighbour , neighbour . ExternalEndPoint , newAgent ,
2008-05-01 18:04:42 +00:00
InformClientOfNeighbourCompleted ,
d ) ;
}
2009-09-07 16:57:30 +00:00
catch ( ArgumentOutOfRangeException )
{
m_log . ErrorFormat (
"[REGIONINFO]: Neighbour Regions response included the current region in the neighbor list. The following region will not display to the client: {0} for region {1} ({2}, {3})." ,
neighbour . ExternalHostName ,
neighbour . RegionHandle ,
neighbour . RegionLocX ,
neighbour . RegionLocY ) ;
}
2008-05-01 18:04:42 +00:00
catch ( Exception e )
{
m_log . ErrorFormat (
2008-05-16 01:22:11 +00:00
"[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}" ,
2008-12-14 02:17:12 +00:00
neighbour . ExternalHostName ,
neighbour . RegionHandle ,
neighbour . RegionLocX ,
neighbour . RegionLocY ,
2008-05-01 18:04:42 +00:00
e ) ;
2008-05-16 01:22:11 +00:00
2008-05-01 18:04:42 +00:00
// FIXME: Okay, even though we've failed, we're still going to throw the exception on,
// since I don't know what will happen if we just let the client continue
2008-05-16 01:22:11 +00:00
2008-05-01 18:04:42 +00:00
// XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
2008-05-16 01:22:11 +00:00
// throw e;
}
2008-05-01 18:04:42 +00:00
}
2008-12-14 02:17:12 +00:00
count + + ;
2008-05-01 18:04:42 +00:00
}
}
/// <summary>
/// This informs a single neighboring region about agent "avatar".
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary>
2009-02-14 16:37:55 +00:00
public void InformNeighborChildAgent ( ScenePresence avatar , SimpleRegionInfo region )
2008-05-01 18:04:42 +00:00
{
AgentCircuitData agent = avatar . ControllingClient . RequestClientInfo ( ) ;
2008-09-06 07:52:41 +00:00
agent . BaseFolder = UUID . Zero ;
agent . InventoryFolder = UUID . Zero ;
agent . startpos = new Vector3 ( 128 , 128 , 70 ) ;
2008-05-01 18:04:42 +00:00
agent . child = true ;
InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync ;
2008-12-15 16:23:34 +00:00
d . BeginInvoke ( avatar , agent , region , region . ExternalEndPoint , true ,
2008-05-01 18:04:42 +00:00
InformClientOfNeighbourCompleted ,
d ) ;
}
# endregion
2009-06-14 15:35:09 +00:00
public delegate void InformNeighbourThatRegionUpDelegate ( INeighbourService nService , RegionInfo region , ulong regionhandle ) ;
2008-05-01 18:04:42 +00:00
2007-11-29 02:07:19 +00:00
private void InformNeighborsThatRegionisUpCompleted ( IAsyncResult iar )
{
2007-12-27 21:41:48 +00:00
InformNeighbourThatRegionUpDelegate icon = ( InformNeighbourThatRegionUpDelegate ) iar . AsyncState ;
2007-11-29 02:07:19 +00:00
icon . EndInvoke ( iar ) ;
}
2008-03-22 22:17:35 +00:00
/// <summary>
/// Asynchronous call to information neighbouring regions that this region is up
/// </summary>
/// <param name="region"></param>
/// <param name="regionhandle"></param>
2009-06-14 15:35:09 +00:00
private void InformNeighboursThatRegionIsUpAsync ( INeighbourService neighbourService , RegionInfo region , ulong regionhandle )
2007-11-29 02:07:19 +00:00
{
2008-02-05 19:44:27 +00:00
m_log . Info ( "[INTERGRID]: Starting to inform neighbors that I'm here" ) ;
2008-03-30 08:01:47 +00:00
//RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
2009-02-14 16:37:55 +00:00
//bool regionAccepted =
// m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle);
2009-06-14 15:35:09 +00:00
//bool regionAccepted = m_interregionCommsOut.SendHelloNeighbour(regionhandle, region);
bool regionAccepted = false ;
if ( neighbourService ! = null )
regionAccepted = neighbourService . HelloNeighbour ( regionhandle , region ) ;
else
m_log . DebugFormat ( "[SCS]: No neighbour service provided for informing neigbhours of this region" ) ;
2007-11-29 02:07:19 +00:00
if ( regionAccepted )
{
2008-02-05 19:44:27 +00:00
m_log . Info ( "[INTERGRID]: Completed informing neighbors that I'm here" ) ;
2008-05-13 06:05:45 +00:00
handlerRegionUp = OnRegionUp ;
2008-05-16 01:22:11 +00:00
2008-05-13 06:05:45 +00:00
// yes, we're notifying ourselves.
if ( handlerRegionUp ! = null )
handlerRegionUp ( region ) ;
2007-11-29 02:07:19 +00:00
}
else
{
2008-03-22 22:17:35 +00:00
m_log . Warn ( "[INTERGRID]: Failed to inform neighbors that I'm here." ) ;
2007-11-29 02:07:19 +00:00
}
}
2007-12-27 21:41:48 +00:00
2007-12-10 21:12:38 +00:00
/// <summary>
/// Called by scene when region is initialized (not always when it's listening for agents)
/// This is an inter-region message that informs the surrounding neighbors that the sim is up.
/// </summary>
2009-06-14 15:35:09 +00:00
public void InformNeighborsThatRegionisUp ( INeighbourService neighbourService , RegionInfo region )
2007-11-29 02:07:19 +00:00
{
2008-02-05 19:44:27 +00:00
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
2007-11-29 06:06:42 +00:00
2009-02-14 16:37:55 +00:00
2007-11-29 07:25:58 +00:00
List < SimpleRegionInfo > neighbours = new List < SimpleRegionInfo > ( ) ;
2007-12-10 19:16:50 +00:00
// This stays uncached because we don't already know about our neighbors at this point.
2007-11-29 07:25:58 +00:00
neighbours = m_commsProvider . GridService . RequestNeighbours ( m_regionInfo . RegionLocX , m_regionInfo . RegionLocY ) ;
2007-11-29 06:06:42 +00:00
if ( neighbours ! = null )
{
for ( int i = 0 ; i < neighbours . Count ; i + + )
{
InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync ;
2009-06-14 15:35:09 +00:00
d . BeginInvoke ( neighbourService , region , neighbours [ i ] . RegionHandle ,
2007-11-29 06:06:42 +00:00
InformNeighborsThatRegionisUpCompleted ,
d ) ;
}
}
2007-12-27 21:41:48 +00:00
2008-05-14 17:03:25 +00:00
//bool val = m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region));
2007-11-29 02:07:19 +00:00
}
2007-12-27 21:41:48 +00:00
2009-01-03 02:29:49 +00:00
public delegate void SendChildAgentDataUpdateDelegate ( AgentPosition cAgentData , ulong regionHandle ) ;
2008-05-01 18:04:42 +00:00
2007-12-10 21:12:38 +00:00
/// <summary>
/// This informs all neighboring regions about the settings of it's child agent.
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
2008-05-16 01:22:11 +00:00
///
2007-12-10 21:12:38 +00:00
/// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
2008-05-16 01:22:11 +00:00
///
2007-12-10 21:12:38 +00:00
/// </summary>
2009-01-03 02:29:49 +00:00
private void SendChildAgentDataUpdateAsync ( AgentPosition cAgentData , ulong regionHandle )
2007-12-10 00:46:56 +00:00
{
2009-01-01 19:42:24 +00:00
//m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
2008-01-26 17:00:35 +00:00
try
2007-12-10 00:46:56 +00:00
{
2008-12-29 22:22:05 +00:00
//m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
m_interregionCommsOut . SendChildAgentUpdate ( regionHandle , cAgentData ) ;
2007-12-10 00:46:56 +00:00
}
2008-12-22 07:06:01 +00:00
catch
2008-01-26 17:00:35 +00:00
{
2008-12-22 07:06:01 +00:00
// Ignore; we did our best
2008-01-26 17:00:35 +00:00
}
2008-05-01 18:04:42 +00:00
2008-12-22 07:06:01 +00:00
//if (regionAccepted)
//{
// //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
//}
//else
//{
// //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
//}
2007-12-10 00:46:56 +00:00
}
2007-12-27 21:41:48 +00:00
2007-12-10 00:46:56 +00:00
private void SendChildAgentDataUpdateCompleted ( IAsyncResult iar )
{
2007-12-27 21:41:48 +00:00
SendChildAgentDataUpdateDelegate icon = ( SendChildAgentDataUpdateDelegate ) iar . AsyncState ;
2007-12-10 00:46:56 +00:00
icon . EndInvoke ( iar ) ;
}
2007-12-27 21:41:48 +00:00
2009-01-03 02:29:49 +00:00
public void SendChildAgentDataUpdate ( AgentPosition cAgentData , ScenePresence presence )
2007-12-10 00:46:56 +00:00
{
// This assumes that we know what our neighbors are.
2008-12-22 07:06:01 +00:00
try
{
foreach ( ulong regionHandle in presence . KnownChildRegionHandles )
{
2008-12-29 22:22:05 +00:00
if ( regionHandle ! = m_regionInfo . RegionHandle )
{
SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync ;
d . BeginInvoke ( cAgentData , regionHandle ,
SendChildAgentDataUpdateCompleted ,
d ) ;
}
2008-12-22 07:06:01 +00:00
}
}
catch ( InvalidOperationException )
{
// We're ignoring a collection was modified error because this data gets old and outdated fast.
}
2007-12-10 00:46:56 +00:00
}
2007-12-27 21:41:48 +00:00
2008-12-22 07:06:01 +00:00
public delegate void SendCloseChildAgentDelegate ( UUID agentID , ulong regionHandle ) ;
2008-05-01 18:04:42 +00:00
2008-01-21 23:04:42 +00:00
/// <summary>
2008-01-22 08:52:51 +00:00
/// This Closes child agents on neighboring regions
2008-01-21 23:04:42 +00:00
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary>
2008-12-22 07:06:01 +00:00
protected void SendCloseChildAgentAsync ( UUID agentID , ulong regionHandle )
2008-01-21 23:04:42 +00:00
{
2008-05-01 18:04:42 +00:00
2008-12-22 07:06:01 +00:00
m_log . Debug ( "[INTERGRID]: Sending close agent to " + regionHandle ) ;
// let's do our best, but there's not much we can do if the neighbour doesn't accept.
2008-05-16 01:22:11 +00:00
2009-01-01 19:42:24 +00:00
//m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
m_interregionCommsOut . SendCloseAgent ( regionHandle , agentID ) ;
2008-01-21 23:04:42 +00:00
}
private void SendCloseChildAgentCompleted ( IAsyncResult iar )
{
2008-05-01 18:04:42 +00:00
SendCloseChildAgentDelegate icon = ( SendCloseChildAgentDelegate ) iar . AsyncState ;
2008-01-21 23:04:42 +00:00
icon . EndInvoke ( iar ) ;
}
2008-09-06 07:52:41 +00:00
public void SendCloseChildAgentConnections ( UUID agentID , List < ulong > regionslst )
2008-01-21 23:04:42 +00:00
{
2008-12-22 07:06:01 +00:00
foreach ( ulong handle in regionslst )
{
SendCloseChildAgentDelegate d = SendCloseChildAgentAsync ;
d . BeginInvoke ( agentID , handle ,
SendCloseChildAgentCompleted ,
d ) ;
}
2008-01-21 23:04:42 +00:00
}
2007-11-29 06:06:42 +00:00
2007-11-04 14:34:45 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Helper function to request neighbors from grid-comms
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="regionHandle"></param>
/// <returns></returns>
public virtual RegionInfo RequestNeighbouringRegionInfo ( ulong regionHandle )
{
2008-02-05 19:44:27 +00:00
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
2007-11-04 14:34:45 +00:00
return m_commsProvider . GridService . RequestNeighbourInfo ( regionHandle ) ;
}
2008-08-14 00:04:37 +00:00
/// <summary>
/// Helper function to request neighbors from grid-comms
/// </summary>
/// <param name="regionID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public virtual RegionInfo RequestNeighbouringRegionInfo ( UUID regionID )
2008-08-14 00:04:37 +00:00
{
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionID);
return m_commsProvider . GridService . RequestNeighbourInfo ( regionID ) ;
}
2007-11-04 14:34:45 +00:00
/// <summary>
2007-12-10 21:12:38 +00:00
/// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="minX"></param>
/// <param name="minY"></param>
/// <param name="maxX"></param>
/// <param name="maxY"></param>
public virtual void RequestMapBlocks ( IClientAPI remoteClient , int minX , int minY , int maxX , int maxY )
{
List < MapBlockData > mapBlocks ;
2007-11-29 06:06:42 +00:00
mapBlocks = m_commsProvider . GridService . RequestNeighbourMapBlocks ( minX - 4 , minY - 4 , minX + 4 , minY + 4 ) ;
2008-06-25 20:14:47 +00:00
remoteClient . SendMapBlock ( mapBlocks , 0 ) ;
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-03-20 20:04:45 +00:00
/// Try to teleport an agent to a new region.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="RegionHandle"></param>
/// <param name="position"></param>
/// <param name="lookAt"></param>
/// <param name="flags"></param>
2008-09-06 07:52:41 +00:00
public virtual void RequestTeleportToLocation ( ScenePresence avatar , ulong regionHandle , Vector3 position ,
2008-09-12 20:12:03 +00:00
Vector3 lookAt , uint teleportFlags )
2007-11-04 14:34:45 +00:00
{
2008-11-21 22:14:57 +00:00
if ( ! avatar . Scene . Permissions . CanTeleport ( avatar . UUID ) )
2008-10-11 22:11:48 +00:00
return ;
2009-01-18 01:45:22 +00:00
bool destRegionUp = true ;
2008-08-18 00:39:10 +00:00
2008-10-03 09:53:49 +00:00
IEventQueue eq = avatar . Scene . RequestModuleInterface < IEventQueue > ( ) ;
2009-02-18 21:28:54 +00:00
// Reset animations; the viewer does that in teleports.
avatar . ResetAnimations ( ) ;
2007-11-04 14:34:45 +00:00
if ( regionHandle = = m_regionInfo . RegionHandle )
{
2009-01-19 17:15:27 +00:00
m_log . DebugFormat (
2009-08-28 23:42:28 +00:00
"[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}" ,
2009-01-19 17:15:27 +00:00
position , m_regionInfo . RegionName ) ;
2009-08-28 23:42:28 +00:00
2008-08-01 18:49:48 +00:00
// Teleport within the same region
2009-08-28 23:42:28 +00:00
if ( IsOutsideRegion ( avatar . Scene , position ) | | position . Z < 0 )
2008-08-27 02:49:47 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 emergencyPos = new Vector3 ( 128 , 128 , 128 ) ;
2008-08-27 02:49:47 +00:00
m_log . WarnFormat (
"[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}" ,
position , avatar . Name , avatar . UUID , emergencyPos ) ;
position = emergencyPos ;
}
2009-08-28 23:42:28 +00:00
2008-08-27 02:49:47 +00:00
// TODO: Get proper AVG Height
float localAVHeight = 1.56f ;
2009-08-28 23:42:28 +00:00
float posZLimit = 22 ;
// TODO: Check other Scene HeightField
if ( position . X > 0 & & position . X < = ( int ) Constants . RegionSize & & position . Y > 0 & & position . Y < = ( int ) Constants . RegionSize )
{
posZLimit = ( float ) avatar . Scene . Heightmap [ ( int ) position . X , ( int ) position . Y ] ;
}
2008-08-27 02:49:47 +00:00
float newPosZ = posZLimit + localAVHeight ;
if ( posZLimit > = ( position . Z - ( localAVHeight / 2 ) ) & & ! ( Single . IsInfinity ( newPosZ ) | | Single . IsNaN ( newPosZ ) ) )
{
position . Z = newPosZ ;
}
2008-10-03 09:53:49 +00:00
// Only send this if the event queue is null
if ( eq = = null )
avatar . ControllingClient . SendTeleportLocationStart ( ) ;
2008-09-12 20:12:03 +00:00
avatar . ControllingClient . SendLocalTeleport ( position , lookAt , teleportFlags ) ;
2007-11-04 14:34:45 +00:00
avatar . Teleport ( position ) ;
}
else
{
RegionInfo reg = RequestNeighbouringRegionInfo ( regionHandle ) ;
if ( reg ! = null )
{
2009-01-19 17:15:27 +00:00
m_log . DebugFormat (
2009-01-21 18:46:44 +00:00
"[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}" ,
2009-01-19 17:15:27 +00:00
position , reg . RegionName ) ;
2008-10-03 09:53:49 +00:00
if ( eq = = null )
avatar . ControllingClient . SendTeleportLocationStart ( ) ;
2008-12-20 18:15:02 +00:00
// Let's do DNS resolution only once in this process, please!
// This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
// it's actually doing a lot of work.
IPEndPoint endPoint = reg . ExternalEndPoint ;
if ( endPoint . Address = = null )
{
// Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
destRegionUp = false ;
}
2008-05-14 05:11:23 +00:00
if ( destRegionUp )
2007-11-27 15:44:39 +00:00
{
2008-12-14 02:17:12 +00:00
uint newRegionX = ( uint ) ( reg . RegionHandle > > 40 ) ;
uint newRegionY = ( ( ( uint ) ( reg . RegionHandle ) ) > > 8 ) ;
uint oldRegionX = ( uint ) ( m_regionInfo . RegionHandle > > 40 ) ;
uint oldRegionY = ( ( ( uint ) ( m_regionInfo . RegionHandle ) ) > > 8 ) ;
2008-11-29 13:49:20 +00:00
2008-08-27 02:40:14 +00:00
// Fixing a bug where teleporting while sitting results in the avatar ending up removed from
// both regions
if ( avatar . ParentID ! = ( uint ) 0 )
avatar . StandUp ( ) ;
2009-01-16 21:56:13 +00:00
2008-08-28 14:41:54 +00:00
if ( ! avatar . ValidateAttachments ( ) )
2008-08-20 01:48:51 +00:00
{
avatar . ControllingClient . SendTeleportFailed ( "Inconsistent attachment state" ) ;
return ;
}
2008-11-03 19:56:47 +00:00
// the avatar.Close below will clear the child region list. We need this below for (possibly)
// closing the child agents, so save it here (we need a copy as it is Clear()-ed).
2008-12-14 02:17:12 +00:00
//List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
2008-05-16 01:22:11 +00:00
// Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
2008-03-25 18:47:14 +00:00
// failure at this point (unlike a border crossing failure). So perhaps this can never fail
// once we reach here...
2008-12-14 02:17:12 +00:00
//avatar.Scene.RemoveCapsHandler(avatar.UUID);
2008-12-15 16:23:34 +00:00
string capsPath = String . Empty ;
2008-12-31 00:18:24 +00:00
AgentCircuitData agentCircuit = avatar . ControllingClient . RequestClientInfo ( ) ;
agentCircuit . BaseFolder = UUID . Zero ;
agentCircuit . InventoryFolder = UUID . Zero ;
agentCircuit . startpos = position ;
agentCircuit . child = true ;
2009-01-16 21:56:13 +00:00
2008-12-14 02:17:12 +00:00
if ( Util . IsOutsideView ( oldRegionX , newRegionX , oldRegionY , newRegionY ) )
{
2008-12-22 07:06:01 +00:00
// brand new agent, let's create a new caps seed
2009-01-06 18:26:27 +00:00
agentCircuit . CapsPath = CapsUtil . GetRandomCapsObjectPath ( ) ;
2008-12-22 07:06:01 +00:00
}
2008-12-15 16:23:34 +00:00
2009-05-05 16:17:52 +00:00
string reason = String . Empty ;
2008-12-31 00:18:24 +00:00
// Let's create an agent there if one doesn't exist yet.
2009-01-03 07:05:33 +00:00
//if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
2009-05-05 16:17:52 +00:00
if ( ! m_interregionCommsOut . SendCreateChildAgent ( reg . RegionHandle , agentCircuit , out reason ) )
2008-12-22 07:06:01 +00:00
{
2009-05-05 16:17:52 +00:00
avatar . ControllingClient . SendTeleportFailed ( String . Format ( "Destination is not accepting teleports: {0}" ,
reason ) ) ;
2008-12-22 07:06:01 +00:00
return ;
}
2008-12-20 02:45:12 +00:00
2008-12-31 00:18:24 +00:00
// OK, it got this agent. Let's close some child agents
avatar . CloseChildAgents ( newRegionX , newRegionY ) ;
2008-12-22 07:06:01 +00:00
if ( Util . IsOutsideView ( oldRegionX , newRegionX , oldRegionY , newRegionY ) )
{
2009-05-23 06:29:08 +00:00
#region IP Translation for NAT
IClientIPEndpoint ipepClient ;
if ( avatar . ClientView . TryGet ( out ipepClient ) )
{
capsPath
= "http://"
+ NetworkUtil . GetHostFor ( ipepClient . EndPoint , reg . ExternalHostName )
+ ":"
+ reg . HttpPort
+ CapsUtil . GetCapsSeedPath ( agentCircuit . CapsPath ) ;
}
else
{
capsPath
= "http://"
+ reg . ExternalHostName
+ ":"
+ reg . HttpPort
+ CapsUtil . GetCapsSeedPath ( agentCircuit . CapsPath ) ;
}
# endregion
2008-12-15 16:23:34 +00:00
if ( eq ! = null )
{
2009-05-23 05:44:18 +00:00
#region IP Translation for NAT
2009-05-23 06:29:08 +00:00
// Uses ipepClient above
2009-05-23 05:44:18 +00:00
if ( avatar . ClientView . TryGet ( out ipepClient ) )
{
endPoint . Address = NetworkUtil . GetIPFor ( ipepClient . EndPoint , endPoint . Address ) ;
}
# endregion
2009-02-06 16:55:34 +00:00
eq . EnableSimulator ( reg . RegionHandle , endPoint , avatar . UUID ) ;
2008-12-15 16:23:34 +00:00
2008-12-22 07:06:01 +00:00
// ES makes the client send a UseCircuitCode message to the destination,
// which triggers a bunch of things there.
// So let's wait
Thread . Sleep ( 2000 ) ;
2009-02-06 16:55:34 +00:00
eq . EstablishAgentCommunication ( avatar . UUID , endPoint , capsPath ) ;
2008-12-15 16:23:34 +00:00
}
else
{
2008-12-20 18:15:02 +00:00
avatar . ControllingClient . InformClientOfNeighbour ( reg . RegionHandle , endPoint ) ;
2008-12-15 16:23:34 +00:00
}
2008-12-14 02:17:12 +00:00
}
else
{
2009-01-21 21:14:17 +00:00
agentCircuit . CapsPath = avatar . Scene . CapsModule . GetChildSeed ( avatar . UUID , reg . RegionHandle ) ;
2008-12-15 16:23:34 +00:00
capsPath = "http://" + reg . ExternalHostName + ":" + reg . HttpPort
2008-12-31 00:18:24 +00:00
+ "/CAPS/" + agentCircuit . CapsPath + "0000/" ;
2008-12-14 02:17:12 +00:00
}
2008-12-20 22:44:26 +00:00
// Expect avatar crossing is a heavy-duty function at the destination.
// That is where MakeRoot is called, which fetches appearance and inventory.
// Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
2008-12-22 07:06:01 +00:00
//m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
// position, false);
2008-12-18 19:45:55 +00:00
//{
// avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
// // We should close that agent we just created over at destination...
// List<ulong> lst = new List<ulong>();
// lst.Add(reg.RegionHandle);
// SendCloseChildAgentAsync(avatar.UUID, lst);
// return;
//}
2008-12-14 02:17:12 +00:00
2009-01-01 19:42:24 +00:00
SetInTransit ( avatar . UUID ) ;
2008-12-31 00:18:24 +00:00
// Let's send a full update of the agent. This is a synchronous call.
AgentData agent = new AgentData ( ) ;
avatar . CopyTo ( agent ) ;
2009-01-03 02:29:49 +00:00
agent . Position = position ;
2009-01-01 19:42:24 +00:00
agent . CallbackURI = "http://" + m_regionInfo . ExternalHostName + ":" + m_regionInfo . HttpPort +
"/agent/" + avatar . UUID . ToString ( ) + "/" + avatar . Scene . RegionInfo . RegionHandle . ToString ( ) + "/release/" ;
2008-12-31 00:18:24 +00:00
m_interregionCommsOut . SendChildAgentUpdate ( reg . RegionHandle , agent ) ;
2008-03-25 18:47:14 +00:00
m_log . DebugFormat (
2008-05-16 01:22:11 +00:00
"[CAPS]: Sending new CAPS seed url {0} to client {1}" , capsPath , avatar . UUID ) ;
2008-10-03 09:53:49 +00:00
2008-09-28 14:19:26 +00:00
if ( eq ! = null )
{
2009-02-06 16:55:34 +00:00
eq . TeleportFinishEvent ( reg . RegionHandle , 13 , endPoint ,
4 , teleportFlags , capsPath , avatar . UUID ) ;
2008-09-28 14:19:26 +00:00
}
else
{
2008-12-20 18:15:02 +00:00
avatar . ControllingClient . SendRegionTeleport ( reg . RegionHandle , 13 , endPoint , 4 ,
2008-09-28 14:19:26 +00:00
teleportFlags , capsPath ) ;
}
2009-01-01 19:42:24 +00:00
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
// that the client contacted the destination before we send the attachments and close things here.
if ( ! WaitForCallback ( avatar . UUID ) )
{
// Client never contacted destination. Let's restore everything back
avatar . ControllingClient . SendTeleportFailed ( "Problems connecting to destination." ) ;
ResetFromTransit ( avatar . UUID ) ;
2009-01-19 17:15:27 +00:00
2009-01-01 19:42:24 +00:00
// Yikes! We should just have a ref to scene here.
avatar . Scene . InformClientOfNeighbours ( avatar ) ;
// Finally, kill the agent we just created at the destination.
m_interregionCommsOut . SendCloseAgent ( reg . RegionHandle , avatar . UUID ) ;
return ;
}
// Can't go back from here
2008-09-06 07:52:41 +00:00
if ( KiPrimitive ! = null )
2008-01-19 20:34:54 +00:00
{
2008-09-06 07:52:41 +00:00
KiPrimitive ( avatar . LocalId ) ;
2008-01-19 20:34:54 +00:00
}
2008-11-07 05:48:44 +00:00
2009-01-01 19:42:24 +00:00
avatar . MakeChildAgent ( ) ;
2008-12-22 17:43:51 +00:00
// CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
avatar . CrossAttachmentsIntoNewRegion ( reg . RegionHandle , true ) ;
2008-11-07 05:48:44 +00:00
2008-12-14 02:17:12 +00:00
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
2008-12-15 16:23:34 +00:00
if ( Util . IsOutsideView ( oldRegionX , newRegionX , oldRegionY , newRegionY ) )
{
2009-01-01 19:42:24 +00:00
Thread . Sleep ( 5000 ) ;
2008-12-22 07:06:01 +00:00
avatar . Close ( ) ;
2008-12-15 16:23:34 +00:00
CloseConnection ( avatar . UUID ) ;
}
2009-02-18 01:49:18 +00:00
else
// now we have a child agent in this region.
avatar . Reset ( ) ;
2008-11-30 23:36:56 +00:00
2008-08-12 06:21:02 +00:00
// if (teleport success) // seems to be always success here
2008-08-19 15:09:35 +00:00
// the user may change their profile information in other region,
2008-08-12 06:21:02 +00:00
// so the userinfo in UserProfileCache is not reliable any more, delete it
2008-08-19 15:09:35 +00:00
if ( avatar . Scene . NeedSceneCacheClear ( avatar . UUID ) )
2008-12-15 16:23:34 +00:00
{
2008-08-19 15:09:35 +00:00
m_commsProvider . UserProfileCacheService . RemoveUser ( avatar . UUID ) ;
2009-01-14 18:46:33 +00:00
m_log . DebugFormat (
"[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed" ,
avatar . UUID ) ;
2008-12-15 16:23:34 +00:00
}
2007-11-05 13:58:44 +00:00
}
2008-01-20 19:12:00 +00:00
else
{
avatar . ControllingClient . SendTeleportFailed ( "Remote Region appears to be down" ) ;
}
2007-11-04 14:34:45 +00:00
}
2008-10-04 18:08:35 +00:00
else
{
// TP to a place that doesn't exist (anymore)
// Inform the viewer about that
avatar . ControllingClient . SendTeleportFailed ( "The region you tried to teleport to doesn't exist anymore" ) ;
// and set the map-tile to '(Offline)'
uint regX , regY ;
2008-11-19 06:25:34 +00:00
Utils . LongToUInts ( regionHandle , out regX , out regY ) ;
2008-10-04 18:08:35 +00:00
MapBlockData block = new MapBlockData ( ) ;
block . X = ( ushort ) ( regX / Constants . RegionSize ) ;
block . Y = ( ushort ) ( regY / Constants . RegionSize ) ;
block . Access = 254 ; // == not there
List < MapBlockData > blocks = new List < MapBlockData > ( ) ;
blocks . Add ( block ) ;
avatar . ControllingClient . SendMapBlock ( blocks , 0 ) ;
}
2007-11-04 14:34:45 +00:00
}
}
2009-08-28 23:42:28 +00:00
private bool IsOutsideRegion ( Scene s , Vector3 pos )
{
if ( s . TestBorderCross ( pos , Cardinals . N ) )
return true ;
if ( s . TestBorderCross ( pos , Cardinals . S ) )
return true ;
if ( s . TestBorderCross ( pos , Cardinals . E ) )
return true ;
if ( s . TestBorderCross ( pos , Cardinals . W ) )
return true ;
return false ;
}
2009-02-08 00:54:56 +00:00
public bool WaitForCallback ( UUID id )
2009-01-01 19:42:24 +00:00
{
2009-08-13 21:10:12 +00:00
int count = 200 ;
2009-01-01 19:42:24 +00:00
while ( m_agentsInTransit . Contains ( id ) & & count - - > 0 )
{
2009-02-22 20:52:55 +00:00
//m_log.Debug(" >>> Waiting... " + count);
2009-08-13 21:10:12 +00:00
Thread . Sleep ( 100 ) ;
2009-01-01 19:42:24 +00:00
}
if ( count > 0 )
return true ;
else
return false ;
}
public bool ReleaseAgent ( UUID id )
{
2009-02-22 20:52:55 +00:00
//m_log.Debug(" >>> ReleaseAgent called <<< ");
2009-01-01 19:42:24 +00:00
return ResetFromTransit ( id ) ;
}
2009-02-08 00:54:56 +00:00
public void SetInTransit ( UUID id )
2009-01-01 19:42:24 +00:00
{
lock ( m_agentsInTransit )
{
if ( ! m_agentsInTransit . Contains ( id ) )
m_agentsInTransit . Add ( id ) ;
}
}
protected bool ResetFromTransit ( UUID id )
{
lock ( m_agentsInTransit )
{
if ( m_agentsInTransit . Contains ( id ) )
{
m_agentsInTransit . Remove ( id ) ;
return true ;
}
}
return false ;
}
2008-12-14 02:17:12 +00:00
private List < ulong > NeighbourHandles ( List < SimpleRegionInfo > neighbours )
{
List < ulong > handles = new List < ulong > ( ) ;
foreach ( SimpleRegionInfo reg in neighbours )
{
handles . Add ( reg . RegionHandle ) ;
}
return handles ;
}
private List < ulong > NewNeighbours ( List < ulong > currentNeighbours , List < ulong > previousNeighbours )
{
return currentNeighbours . FindAll ( delegate ( ulong handle ) { return ! previousNeighbours . Contains ( handle ) ; } ) ;
}
2008-12-17 18:42:23 +00:00
// private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
// {
// return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
// }
2008-12-14 02:17:12 +00:00
private List < ulong > OldNeighbours ( List < ulong > currentNeighbours , List < ulong > previousNeighbours )
{
return previousNeighbours . FindAll ( delegate ( ulong handle ) { return ! currentNeighbours . Contains ( handle ) ; } ) ;
}
2007-11-04 14:34:45 +00:00
2009-02-12 23:23:44 +00:00
public void CrossAgentToNewRegion ( Scene scene , ScenePresence agent , bool isFlying )
{
Vector3 pos = agent . AbsolutePosition ;
Vector3 newpos = new Vector3 ( pos . X , pos . Y , pos . Z ) ;
uint neighbourx = m_regionInfo . RegionLocX ;
uint neighboury = m_regionInfo . RegionLocY ;
2009-08-30 03:39:27 +00:00
const float boundaryDistance = 1.7f ;
2009-09-02 08:39:00 +00:00
Vector3 northCross = new Vector3 ( 0 , boundaryDistance , 0 ) ;
2009-08-30 03:39:27 +00:00
Vector3 southCross = new Vector3 ( 0 , - 1 * boundaryDistance , 0 ) ;
Vector3 eastCross = new Vector3 ( boundaryDistance , 0 , 0 ) ;
Vector3 westCross = new Vector3 ( - 1 * boundaryDistance , 0 , 0 ) ;
2009-02-12 23:23:44 +00:00
// distance to edge that will trigger crossing
2009-08-30 03:39:27 +00:00
2009-02-12 23:23:44 +00:00
// distance into new region to place avatar
2009-08-30 03:39:27 +00:00
const float enterDistance = 0.5f ;
2009-02-12 23:23:44 +00:00
2009-08-30 03:39:27 +00:00
if ( scene . TestBorderCross ( pos + westCross , Cardinals . W ) )
2009-08-28 23:42:28 +00:00
{
2009-08-30 03:39:27 +00:00
if ( scene . TestBorderCross ( pos + northCross , Cardinals . N ) )
2009-08-28 23:42:28 +00:00
{
2009-08-30 03:39:27 +00:00
Border b = scene . GetCrossedBorder ( pos + northCross , Cardinals . N ) ;
2009-08-28 23:42:28 +00:00
neighboury + = ( uint ) ( int ) ( b . BorderLine . Z / ( int ) Constants . RegionSize ) ;
}
2009-08-30 03:39:27 +00:00
else if ( scene . TestBorderCross ( pos + southCross , Cardinals . S ) )
{
neighboury - - ;
newpos . Y = Constants . RegionSize - enterDistance ;
}
2009-08-28 23:42:28 +00:00
neighbourx - - ;
newpos . X = Constants . RegionSize - enterDistance ;
}
2009-08-30 03:39:27 +00:00
else if ( scene . TestBorderCross ( pos + eastCross , Cardinals . E ) )
2009-08-28 23:42:28 +00:00
{
2009-08-30 03:39:27 +00:00
Border b = scene . GetCrossedBorder ( pos + eastCross , Cardinals . E ) ;
neighbourx + = ( uint ) ( int ) ( b . BorderLine . Z / ( int ) Constants . RegionSize ) ;
newpos . X = enterDistance ;
if ( scene . TestBorderCross ( pos + southCross , Cardinals . S ) )
2009-08-28 23:42:28 +00:00
{
neighboury - - ;
newpos . Y = Constants . RegionSize - enterDistance ;
}
2009-08-30 03:39:27 +00:00
else if ( scene . TestBorderCross ( pos + northCross , Cardinals . N ) )
2009-08-28 23:42:28 +00:00
{
2009-08-30 03:39:27 +00:00
Border c = scene . GetCrossedBorder ( pos + northCross , Cardinals . N ) ;
neighboury + = ( uint ) ( int ) ( c . BorderLine . Z / ( int ) Constants . RegionSize ) ;
2009-08-28 23:42:28 +00:00
newpos . Y = enterDistance ;
}
2009-08-30 03:39:27 +00:00
2009-08-28 23:42:28 +00:00
}
2009-08-30 03:39:27 +00:00
else if ( scene . TestBorderCross ( pos + southCross , Cardinals . S ) )
2009-08-28 23:42:28 +00:00
{
neighboury - - ;
newpos . Y = Constants . RegionSize - enterDistance ;
}
2009-08-30 03:39:27 +00:00
else if ( scene . TestBorderCross ( pos + northCross , Cardinals . N ) )
2009-08-28 23:42:28 +00:00
{
2009-08-30 03:39:27 +00:00
Border b = scene . GetCrossedBorder ( pos + northCross , Cardinals . N ) ;
2009-08-28 23:42:28 +00:00
neighboury + = ( uint ) ( int ) ( b . BorderLine . Z / ( int ) Constants . RegionSize ) ;
newpos . Y = enterDistance ;
}
/ *
if ( pos . X < boundaryDistance ) //West
2009-02-12 23:23:44 +00:00
{
neighbourx - - ;
newpos . X = Constants . RegionSize - enterDistance ;
}
2009-08-28 23:42:28 +00:00
else if ( pos . X > Constants . RegionSize - boundaryDistance ) // East
2009-02-12 23:23:44 +00:00
{
neighbourx + + ;
newpos . X = enterDistance ;
}
2009-08-28 23:42:28 +00:00
if ( pos . Y < boundaryDistance ) // South
2009-02-12 23:23:44 +00:00
{
neighboury - - ;
newpos . Y = Constants . RegionSize - enterDistance ;
}
2009-08-28 23:42:28 +00:00
else if ( pos . Y > Constants . RegionSize - boundaryDistance ) // North
2009-02-12 23:23:44 +00:00
{
neighboury + + ;
newpos . Y = enterDistance ;
}
2009-08-28 23:42:28 +00:00
* /
2009-02-12 23:23:44 +00:00
CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync ;
d . BeginInvoke ( agent , newpos , neighbourx , neighboury , isFlying , CrossAgentToNewRegionCompleted , d ) ;
}
public delegate ScenePresence CrossAgentToNewRegionDelegate ( ScenePresence agent , Vector3 pos , uint neighbourx , uint neighboury , bool isFlying ) ;
/// <summary>
/// This Closes child agents on neighboring regions
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary>
protected ScenePresence CrossAgentToNewRegionAsync ( ScenePresence agent , Vector3 pos , uint neighbourx , uint neighboury , bool isFlying )
{
m_log . DebugFormat ( "[SCENE COMM]: Crossing agent {0} {1} to {2}-{3}" , agent . Firstname , agent . Lastname , neighbourx , neighboury ) ;
ulong neighbourHandle = Utils . UIntsToLong ( ( uint ) ( neighbourx * Constants . RegionSize ) , ( uint ) ( neighboury * Constants . RegionSize ) ) ;
SimpleRegionInfo neighbourRegion = RequestNeighbouringRegionInfo ( neighbourHandle ) ;
if ( neighbourRegion ! = null & & agent . ValidateAttachments ( ) )
{
pos = pos + ( agent . Velocity ) ;
2009-08-13 21:10:12 +00:00
//CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
//if (userInfo != null)
//{
// userInfo.DropInventory();
//}
//else
//{
// m_log.WarnFormat("[SCENE COMM]: No cached user info found for {0} {1} on leaving region {2}",
// agent.Name, agent.UUID, agent.Scene.RegionInfo.RegionName);
//}
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
//bool crossingSuccessful =
// CrossToNeighbouringRegion(neighbourHandle, agent.ControllingClient.AgentId, pos,
//isFlying);
SetInTransit ( agent . UUID ) ;
AgentData cAgent = new AgentData ( ) ;
agent . CopyTo ( cAgent ) ;
cAgent . Position = pos ;
if ( isFlying )
cAgent . ControlFlags | = ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_FLY ;
cAgent . CallbackURI = "http://" + m_regionInfo . ExternalHostName + ":" + m_regionInfo . HttpPort +
"/agent/" + agent . UUID . ToString ( ) + "/" + agent . Scene . RegionInfo . RegionHandle . ToString ( ) + "/release/" ;
m_interregionCommsOut . SendChildAgentUpdate ( neighbourHandle , cAgent ) ;
// Next, let's close the child agent connections that are too far away.
agent . CloseChildAgents ( neighbourx , neighboury ) ;
//AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
agent . ControllingClient . RequestClientInfo ( ) ;
2009-02-22 20:52:55 +00:00
//m_log.Debug("BEFORE CROSS");
2009-02-13 03:45:08 +00:00
//Scene.DumpChildrenSeeds(UUID);
//DumpKnownRegions();
string agentcaps ;
if ( ! agent . KnownRegions . TryGetValue ( neighbourRegion . RegionHandle , out agentcaps ) )
2009-02-12 23:23:44 +00:00
{
2009-02-13 03:45:08 +00:00
m_log . ErrorFormat ( "[SCENE COMM]: No CAPS information for region handle {0}, exiting CrossToNewRegion." ,
neighbourRegion . RegionHandle ) ;
return agent ;
}
// TODO Should construct this behind a method
string capsPath =
"http://" + neighbourRegion . ExternalHostName + ":" + neighbourRegion . HttpPort
+ "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/" ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
m_log . DebugFormat ( "[CAPS]: Sending new CAPS seed url {0} to client {1}" , capsPath , agent . UUID ) ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
IEventQueue eq = agent . Scene . RequestModuleInterface < IEventQueue > ( ) ;
if ( eq ! = null )
{
eq . CrossRegion ( neighbourHandle , pos , agent . Velocity , neighbourRegion . ExternalEndPoint ,
capsPath , agent . UUID , agent . ControllingClient . SessionId ) ;
}
else
{
agent . ControllingClient . CrossRegion ( neighbourHandle , pos , agent . Velocity , neighbourRegion . ExternalEndPoint ,
capsPath ) ;
}
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
if ( ! WaitForCallback ( agent . UUID ) )
{
ResetFromTransit ( agent . UUID ) ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
// Yikes! We should just have a ref to scene here.
agent . Scene . InformClientOfNeighbours ( agent ) ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
return agent ;
}
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
agent . MakeChildAgent ( ) ;
// now we have a child agent in this region. Request all interesting data about other (root) agents
agent . SendInitialFullUpdateToAllClients ( ) ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
agent . CrossAttachmentsIntoNewRegion ( neighbourHandle , true ) ;
2009-02-12 23:23:44 +00:00
2009-02-13 03:45:08 +00:00
// m_scene.SendKillObject(m_localId);
agent . Scene . NotifyMyCoarseLocationChange ( ) ;
// the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it
if ( agent . Scene . NeedSceneCacheClear ( agent . UUID ) )
2009-02-12 23:23:44 +00:00
{
2009-02-13 03:45:08 +00:00
agent . Scene . CommsManager . UserProfileCacheService . RemoveUser ( agent . UUID ) ;
m_log . DebugFormat (
"[SCENE COMM]: User {0} is going to another region, profile cache removed" , agent . UUID ) ;
2009-02-12 23:23:44 +00:00
}
}
2009-02-22 20:52:55 +00:00
//m_log.Debug("AFTER CROSS");
2009-02-12 23:23:44 +00:00
//Scene.DumpChildrenSeeds(UUID);
//DumpKnownRegions();
return agent ;
}
private void CrossAgentToNewRegionCompleted ( IAsyncResult iar )
{
CrossAgentToNewRegionDelegate icon = ( CrossAgentToNewRegionDelegate ) iar . AsyncState ;
ScenePresence agent = icon . EndInvoke ( iar ) ;
// If the cross was successful, this agent is a child agent
if ( agent . IsChildAgent )
{
2009-02-18 01:49:18 +00:00
agent . Reset ( ) ;
2009-02-12 23:23:44 +00:00
}
else // Not successful
{
2009-08-13 18:30:29 +00:00
//CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
//if (userInfo != null)
//{
// userInfo.FetchInventory();
//}
2009-02-12 23:23:44 +00:00
agent . RestoreInCurrentScene ( ) ;
}
2009-02-18 20:10:40 +00:00
// In any case
agent . NotInTransit ( ) ;
2009-02-12 23:23:44 +00:00
//m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
}
2007-12-20 06:31:03 +00:00
public Dictionary < string , string > GetGridSettings ( )
{
return m_commsProvider . GridService . GetGridSettings ( ) ;
}
2008-02-16 11:55:09 +00:00
2008-09-12 20:12:03 +00:00
public void LogOffUser ( UUID userid , UUID regionid , ulong regionhandle , Vector3 position , Vector3 lookat )
{
m_commsProvider . LogOffUser ( userid , regionid , regionhandle , position , lookat ) ;
}
// deprecated as of 2008-08-27
2008-09-06 07:52:41 +00:00
public void LogOffUser ( UUID userid , UUID regionid , ulong regionhandle , float posx , float posy , float posz )
2008-02-16 11:55:09 +00:00
{
2008-05-01 18:04:42 +00:00
m_commsProvider . LogOffUser ( userid , regionid , regionhandle , posx , posy , posz ) ;
2008-02-16 11:55:09 +00:00
}
2008-09-06 07:52:41 +00:00
public void ClearUserAgent ( UUID avatarID )
2008-02-16 11:55:09 +00:00
{
2008-07-04 10:19:58 +00:00
m_commsProvider . UserService . ClearUserAgent ( avatarID ) ;
2008-02-16 11:55:09 +00:00
}
2008-09-06 07:52:41 +00:00
public void AddNewUserFriend ( UUID friendlistowner , UUID friend , uint perms )
2008-02-16 11:55:09 +00:00
{
m_commsProvider . AddNewUserFriend ( friendlistowner , friend , perms ) ;
}
2008-09-06 07:52:41 +00:00
public void UpdateUserFriendPerms ( UUID friendlistowner , UUID friend , uint perms )
2008-02-16 11:55:09 +00:00
{
m_commsProvider . UpdateUserFriendPerms ( friendlistowner , friend , perms ) ;
}
2008-09-06 07:52:41 +00:00
public void RemoveUserFriend ( UUID friendlistowner , UUID friend )
2008-02-16 11:55:09 +00:00
{
m_commsProvider . RemoveUserFriend ( friendlistowner , friend ) ;
}
2008-09-06 07:52:41 +00:00
public List < FriendListItem > GetUserFriendList ( UUID friendlistowner )
2008-02-16 11:55:09 +00:00
{
return m_commsProvider . GetUserFriendList ( friendlistowner ) ;
}
2008-05-01 18:04:42 +00:00
public List < MapBlockData > RequestNeighbourMapBlocks ( int minX , int minY , int maxX , int maxY )
2008-02-16 11:55:09 +00:00
{
return m_commsProvider . GridService . RequestNeighbourMapBlocks ( minX , minY , maxX , maxY ) ;
}
2008-09-06 07:52:41 +00:00
public List < AvatarPickerAvatar > GenerateAgentPickerRequestResponse ( UUID queryID , string query )
2008-02-16 11:55:09 +00:00
{
return m_commsProvider . GenerateAgentPickerRequestResponse ( queryID , query ) ;
}
2008-10-03 23:00:42 +00:00
public List < RegionInfo > RequestNamedRegions ( string name , int maxNumber )
{
return m_commsProvider . GridService . RequestNamedRegions ( name , maxNumber ) ;
}
2008-12-14 02:17:12 +00:00
2009-08-11 23:47:36 +00:00
//private void Dump(string msg, List<ulong> handles)
//{
// m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
// foreach (ulong handle in handles)
// {
// uint x, y;
// Utils.LongToUInts(handle, out x, out y);
// x = x / Constants.RegionSize;
// y = y / Constants.RegionSize;
// m_log.InfoFormat("({0}, {1})", x, y);
// }
//}
2007-11-04 14:34:45 +00:00
}
2008-05-01 18:04:42 +00:00
}