SceneCommunicationService.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Net;
  30. using System.Reflection;
  31. using System.Threading;
  32. using libsecondlife;
  33. using log4net;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Communications;
  36. namespace OpenSim.Region.Environment.Scenes
  37. {
  38. public delegate void KillObjectDelegate(uint localID);
  39. public delegate void RemoveKnownRegionsFromAvatarList(LLUUID avatarID, List<ulong> regionlst);
  40. public class SceneCommunicationService //one instance per region
  41. {
  42. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  43. protected CommunicationsManager m_commsProvider;
  44. protected RegionInfo m_regionInfo;
  45. protected RegionCommsListener regionCommsHost;
  46. public event AgentCrossing OnAvatarCrossingIntoRegion;
  47. public event ExpectUserDelegate OnExpectUser;
  48. public event ExpectPrimDelegate OnExpectPrim;
  49. public event CloseAgentConnection OnCloseAgentConnection;
  50. public event PrimCrossing OnPrimCrossingIntoRegion;
  51. public event RegionUp OnRegionUp;
  52. public event ChildAgentUpdate OnChildAgentUpdate;
  53. public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
  54. private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
  55. private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
  56. private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
  57. private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
  58. private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
  59. private RegionUp handlerRegionUp = null; // OnRegionUp;
  60. private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
  61. private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
  62. public KillObjectDelegate KillObject;
  63. public string _debugRegionName = String.Empty;
  64. public string debugRegionName
  65. {
  66. get { return _debugRegionName; }
  67. set { _debugRegionName = value; }
  68. }
  69. public SceneCommunicationService(CommunicationsManager commsMan)
  70. {
  71. m_commsProvider = commsMan;
  72. m_commsProvider.GridService.gdebugRegionName = _debugRegionName;
  73. m_commsProvider.InterRegion.rdebugRegionName = _debugRegionName;
  74. }
  75. public void RegisterRegion(RegionInfo regionInfos)
  76. {
  77. m_regionInfo = regionInfos;
  78. regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo);
  79. if (regionCommsHost != null)
  80. {
  81. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
  82. regionCommsHost.debugRegionName = _debugRegionName;
  83. regionCommsHost.OnExpectPrim += IncomingPrimCrossing;
  84. regionCommsHost.OnExpectUser += NewUserConnection;
  85. regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing;
  86. regionCommsHost.OnCloseAgentConnection += CloseConnection;
  87. regionCommsHost.OnRegionUp += newRegionUp;
  88. regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
  89. }
  90. else
  91. {
  92. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
  93. }
  94. }
  95. public void Close()
  96. {
  97. if (regionCommsHost != null)
  98. {
  99. regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
  100. regionCommsHost.OnRegionUp -= newRegionUp;
  101. regionCommsHost.OnExpectUser -= NewUserConnection;
  102. regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
  103. regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
  104. regionCommsHost.OnCloseAgentConnection -= CloseConnection;
  105. m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
  106. regionCommsHost = null;
  107. }
  108. }
  109. #region CommsManager Event handlers
  110. /// <summary>
  111. ///
  112. /// </summary>
  113. /// <param name="regionHandle"></param>
  114. /// <param name="agent"></param>
  115. ///
  116. protected void NewUserConnection(ulong regionHandle, AgentCircuitData agent)
  117. {
  118. handlerExpectUser = OnExpectUser;
  119. if (handlerExpectUser != null)
  120. {
  121. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
  122. handlerExpectUser(regionHandle, agent);
  123. }
  124. }
  125. protected bool newRegionUp(RegionInfo region)
  126. {
  127. handlerRegionUp = OnRegionUp;
  128. if (handlerRegionUp != null)
  129. {
  130. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
  131. handlerRegionUp(region);
  132. }
  133. return true;
  134. }
  135. protected bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData)
  136. {
  137. handlerChildAgentUpdate = OnChildAgentUpdate;
  138. if (handlerChildAgentUpdate != null)
  139. handlerChildAgentUpdate(regionHandle, cAgentData);
  140. return true;
  141. }
  142. protected void AgentCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying)
  143. {
  144. handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
  145. if (handlerAvatarCrossingIntoRegion != null)
  146. {
  147. handlerAvatarCrossingIntoRegion(regionHandle, agentID, position, isFlying);
  148. }
  149. }
  150. protected bool IncomingPrimCrossing(ulong regionHandle, LLUUID primID, String objXMLData, int XMLMethod)
  151. {
  152. handlerExpectPrim = OnExpectPrim;
  153. if (handlerExpectPrim != null)
  154. {
  155. return handlerExpectPrim(regionHandle, primID, objXMLData, XMLMethod);
  156. }
  157. else
  158. {
  159. return false;
  160. }
  161. }
  162. protected void PrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical)
  163. {
  164. handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion;
  165. if (handlerPrimCrossingIntoRegion != null)
  166. {
  167. handlerPrimCrossingIntoRegion(regionHandle, primID, position, isPhysical);
  168. }
  169. }
  170. protected bool CloseConnection(ulong regionHandle, LLUUID agentID)
  171. {
  172. m_log.Info("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID.ToString());
  173. handlerCloseAgentConnection = OnCloseAgentConnection;
  174. if (handlerCloseAgentConnection != null)
  175. {
  176. return handlerCloseAgentConnection(regionHandle, agentID);
  177. }
  178. return false;
  179. }
  180. #endregion
  181. #region Inform Client of Neighbours
  182. private delegate void InformClientOfNeighbourDelegate(
  183. ScenePresence avatar, AgentCircuitData a, ulong regionHandle, IPEndPoint endPoint);
  184. private void InformClientOfNeighbourCompleted(IAsyncResult iar)
  185. {
  186. InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState;
  187. icon.EndInvoke(iar);
  188. }
  189. /// <summary>
  190. /// Async compnent for informing client of which neighbours exists
  191. /// </summary>
  192. /// <remarks>
  193. /// This needs to run asynchronesously, as a network timeout may block the thread for a long while
  194. /// </remarks>
  195. /// <param name="remoteClient"></param>
  196. /// <param name="a"></param>
  197. /// <param name="regionHandle"></param>
  198. /// <param name="endPoint"></param>
  199. private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, ulong regionHandle,
  200. IPEndPoint endPoint)
  201. {
  202. m_log.Info("[INTERGRID]: Starting to inform client about neighbours");
  203. bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(regionHandle, a);
  204. if (regionAccepted)
  205. {
  206. avatar.ControllingClient.InformClientOfNeighbour(regionHandle, endPoint);
  207. avatar.AddNeighbourRegion(regionHandle);
  208. m_log.Info("[INTERGRID]: Completed inform client about neighbours");
  209. }
  210. }
  211. public void RequestNeighbors(RegionInfo region)
  212. {
  213. List<SimpleRegionInfo> neighbours =
  214. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  215. //IPEndPoint blah = new IPEndPoint();
  216. //blah.Address = region.RemotingAddress;
  217. //blah.Port = region.RemotingPort;
  218. }
  219. /// <summary>
  220. /// This informs all neighboring regions about agent "avatar".
  221. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  222. /// </summary>
  223. public void EnableNeighbourChildAgents(ScenePresence avatar, List<RegionInfo> lstneighbours)
  224. {
  225. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  226. //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  227. for (int i = 0; i < lstneighbours.Count; i++)
  228. {
  229. // We don't want to keep sending to regions that consistently fail on comms.
  230. if (!(lstneighbours[i].commFailTF))
  231. {
  232. neighbours.Add(new SimpleRegionInfo(lstneighbours[i]));
  233. }
  234. }
  235. // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
  236. // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
  237. neighbours =
  238. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  239. if (neighbours != null)
  240. {
  241. for (int i = 0; i < neighbours.Count; i++)
  242. {
  243. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  244. agent.BaseFolder = LLUUID.Zero;
  245. agent.InventoryFolder = LLUUID.Zero;
  246. agent.startpos = new LLVector3(128, 128, 70);
  247. agent.child = true;
  248. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  249. try
  250. {
  251. d.BeginInvoke(avatar, agent, neighbours[i].RegionHandle, neighbours[i].ExternalEndPoint,
  252. InformClientOfNeighbourCompleted,
  253. d);
  254. }
  255. catch (Exception e)
  256. {
  257. m_log.ErrorFormat(
  258. "[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
  259. neighbours[i].ExternalHostName,
  260. neighbours[i].RegionHandle,
  261. neighbours[i].RegionLocX,
  262. neighbours[i].RegionLocY,
  263. e);
  264. // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
  265. // since I don't know what will happen if we just let the client continue
  266. // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
  267. // throw e;
  268. }
  269. }
  270. }
  271. }
  272. /// <summary>
  273. /// This informs a single neighboring region about agent "avatar".
  274. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  275. /// </summary>
  276. public void InformNeighborChildAgent(ScenePresence avatar, RegionInfo region, List<RegionInfo> neighbours)
  277. {
  278. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  279. agent.BaseFolder = LLUUID.Zero;
  280. agent.InventoryFolder = LLUUID.Zero;
  281. agent.startpos = new LLVector3(128, 128, 70);
  282. agent.child = true;
  283. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  284. d.BeginInvoke(avatar, agent, region.RegionHandle, region.ExternalEndPoint,
  285. InformClientOfNeighbourCompleted,
  286. d);
  287. }
  288. #endregion
  289. public delegate void InformNeighbourThatRegionUpDelegate(RegionInfo region, ulong regionhandle);
  290. private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
  291. {
  292. InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
  293. icon.EndInvoke(iar);
  294. }
  295. /// <summary>
  296. /// Asynchronous call to information neighbouring regions that this region is up
  297. /// </summary>
  298. /// <param name="region"></param>
  299. /// <param name="regionhandle"></param>
  300. private void InformNeighboursThatRegionIsUpAsync(RegionInfo region, ulong regionhandle)
  301. {
  302. m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here");
  303. //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
  304. bool regionAccepted =
  305. m_commsProvider.InterRegion.RegionUp(new SearializableRegionInfo(region), regionhandle);
  306. if (regionAccepted)
  307. {
  308. m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here");
  309. }
  310. else
  311. {
  312. m_log.Warn("[INTERGRID]: Failed to inform neighbors that I'm here.");
  313. }
  314. }
  315. /// <summary>
  316. /// Called by scene when region is initialized (not always when it's listening for agents)
  317. /// This is an inter-region message that informs the surrounding neighbors that the sim is up.
  318. /// </summary>
  319. public void InformNeighborsThatRegionisUp(RegionInfo region)
  320. {
  321. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
  322. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  323. // This stays uncached because we don't already know about our neighbors at this point.
  324. neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  325. if (neighbours != null)
  326. {
  327. for (int i = 0; i < neighbours.Count; i++)
  328. {
  329. InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
  330. d.BeginInvoke(region, neighbours[i].RegionHandle,
  331. InformNeighborsThatRegionisUpCompleted,
  332. d);
  333. }
  334. }
  335. //bool val = m_commsProvider.InterRegion.RegionUp(new SearializableRegionInfo(region));
  336. }
  337. public delegate void SendChildAgentDataUpdateDelegate(ChildAgentDataUpdate cAgentData, ScenePresence presence);
  338. /// <summary>
  339. /// This informs all neighboring regions about the settings of it's child agent.
  340. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  341. ///
  342. /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
  343. ///
  344. /// </summary>
  345. private void SendChildAgentDataUpdateAsync(ChildAgentDataUpdate cAgentData, ScenePresence presence)
  346. {
  347. //m_log.Info("[INTERGRID]: Informing neighbors about my agent.");
  348. try
  349. {
  350. foreach (ulong regionHandle in presence.KnownChildRegions)
  351. {
  352. bool regionAccepted = m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
  353. if (regionAccepted)
  354. {
  355. //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
  356. }
  357. else
  358. {
  359. //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
  360. }
  361. }
  362. }
  363. catch (InvalidOperationException)
  364. {
  365. // We're ignoring a collection was modified error because this data gets old and outdated fast.
  366. }
  367. }
  368. private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
  369. {
  370. SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
  371. icon.EndInvoke(iar);
  372. }
  373. public void SendChildAgentDataUpdate(ChildAgentDataUpdate cAgentData, ScenePresence presence)
  374. {
  375. // This assumes that we know what our neighbors are.
  376. SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
  377. d.BeginInvoke(cAgentData,presence,
  378. SendChildAgentDataUpdateCompleted,
  379. d);
  380. }
  381. public delegate void SendCloseChildAgentDelegate( LLUUID agentID, List<ulong> regionlst);
  382. /// <summary>
  383. /// This Closes child agents on neighboring regions
  384. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  385. /// </summary>
  386. private void SendCloseChildAgentAsync(LLUUID agentID, List<ulong> regionlst)
  387. {
  388. foreach (ulong regionHandle in regionlst)
  389. {
  390. bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
  391. if (regionAccepted)
  392. {
  393. m_log.Info("[INTERGRID]: Completed sending agent Close agent Request to neighbor");
  394. }
  395. else
  396. {
  397. m_log.Info("[INTERGRID]: Failed sending agent Close agent Request to neighbor");
  398. }
  399. }
  400. // We remove the list of known regions from the agent's known region list through an event
  401. // to scene, because, if an agent logged of, it's likely that there will be no scene presence
  402. // by the time we get to this part of the method.
  403. handlerRemoveKnownRegionFromAvatar = OnRemoveKnownRegionFromAvatar;
  404. if (handlerRemoveKnownRegionFromAvatar != null)
  405. {
  406. handlerRemoveKnownRegionFromAvatar(agentID, regionlst);
  407. }
  408. }
  409. private void SendCloseChildAgentCompleted(IAsyncResult iar)
  410. {
  411. SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
  412. icon.EndInvoke(iar);
  413. }
  414. public void SendCloseChildAgentConnections(LLUUID agentID, List<ulong> regionslst)
  415. {
  416. // This assumes that we know what our neighbors are.
  417. SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
  418. d.BeginInvoke(agentID, regionslst,
  419. SendCloseChildAgentCompleted,
  420. d);
  421. }
  422. /// <summary>
  423. /// Helper function to request neighbors from grid-comms
  424. /// </summary>
  425. /// <param name="regionHandle"></param>
  426. /// <returns></returns>
  427. public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
  428. {
  429. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
  430. return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle);
  431. }
  432. /// <summary>
  433. /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
  434. /// </summary>
  435. /// <param name="minX"></param>
  436. /// <param name="minY"></param>
  437. /// <param name="maxX"></param>
  438. /// <param name="maxY"></param>
  439. public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
  440. {
  441. List<MapBlockData> mapBlocks;
  442. mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4);
  443. remoteClient.SendMapBlock(mapBlocks);
  444. }
  445. /// <summary>
  446. /// Try to teleport an agent to a new region.
  447. /// </summary>
  448. /// <param name="remoteClient"></param>
  449. /// <param name="RegionHandle"></param>
  450. /// <param name="position"></param>
  451. /// <param name="lookAt"></param>
  452. /// <param name="flags"></param>
  453. public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, LLVector3 position,
  454. LLVector3 lookAt, uint flags)
  455. {
  456. bool destRegionUp = false;
  457. if (regionHandle == m_regionInfo.RegionHandle)
  458. {
  459. avatar.ControllingClient.SendTeleportLocationStart();
  460. avatar.ControllingClient.SendLocalTeleport(position, lookAt, flags);
  461. avatar.Teleport(position);
  462. }
  463. else
  464. {
  465. RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
  466. if (reg != null)
  467. {
  468. avatar.ControllingClient.SendTeleportLocationStart();
  469. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  470. agent.BaseFolder = LLUUID.Zero;
  471. agent.InventoryFolder = LLUUID.Zero;
  472. agent.startpos = position;
  473. agent.child = true;
  474. if (reg.RemotingAddress != "" && reg.RemotingPort != 0)
  475. {
  476. // region is remote. see if it is up
  477. m_commsProvider.InterRegion.CheckRegion(reg.RemotingAddress, reg.RemotingPort);
  478. destRegionUp = m_commsProvider.InterRegion.Available;
  479. }
  480. else
  481. {
  482. // assume local regions are always up
  483. destRegionUp = true;
  484. }
  485. if(destRegionUp)
  486. {
  487. avatar.Close();
  488. // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
  489. // failure at this point (unlike a border crossing failure). So perhaps this can never fail
  490. // once we reach here...
  491. avatar.Scene.RemoveCapsHandler(avatar.UUID);
  492. m_commsProvider.InterRegion.InformRegionOfChildAgent(regionHandle, agent);
  493. m_commsProvider.InterRegion.ExpectAvatarCrossing(regionHandle, avatar.ControllingClient.AgentId,
  494. position, false);
  495. AgentCircuitData circuitdata = avatar.ControllingClient.RequestClientInfo();
  496. // TODO Should construct this behind a method
  497. string capsPath =
  498. "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  499. + "/CAPS/" + circuitdata.CapsPath + "0000/";
  500. m_log.DebugFormat(
  501. "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);
  502. avatar.ControllingClient.SendRegionTeleport(regionHandle, 13, reg.ExternalEndPoint, 4, (1 << 4),
  503. capsPath);
  504. avatar.MakeChildAgent();
  505. Thread.Sleep(5000);
  506. avatar.CrossAttachmentsIntoNewRegion(regionHandle);
  507. if (KillObject != null)
  508. {
  509. KillObject(avatar.LocalId);
  510. }
  511. uint newRegionX = (uint)(regionHandle >> 40);
  512. uint newRegionY = (((uint)(regionHandle)) >> 8);
  513. uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
  514. uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
  515. if (Util.fast_distance2d((int)(newRegionX - oldRegionX), (int)(newRegionY - oldRegionY)) > 3)
  516. {
  517. SendCloseChildAgentConnections(avatar.UUID,avatar.GetKnownRegionList());
  518. }
  519. }
  520. else
  521. {
  522. avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
  523. }
  524. }
  525. }
  526. }
  527. /// <summary>
  528. ///
  529. /// </summary>
  530. /// <param name="regionhandle"></param>
  531. /// <param name="agentID"></param>
  532. /// <param name="position"></param>
  533. public bool CrossToNeighbouringRegion(ulong regionhandle, LLUUID agentID, LLVector3 position, bool isFlying)
  534. {
  535. return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying);
  536. }
  537. public bool PrimCrossToNeighboringRegion(ulong regionhandle, LLUUID primID, string objData, int XMLMethod)
  538. {
  539. return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData, XMLMethod);
  540. }
  541. public Dictionary<string, string> GetGridSettings()
  542. {
  543. return m_commsProvider.GridService.GetGridSettings();
  544. }
  545. public void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz)
  546. {
  547. m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
  548. }
  549. public void ClearUserAgent(LLUUID avatarID)
  550. {
  551. m_commsProvider.UserService.clearUserAgent(avatarID);
  552. }
  553. public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms)
  554. {
  555. m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms);
  556. }
  557. public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms)
  558. {
  559. m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms);
  560. }
  561. public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend)
  562. {
  563. m_commsProvider.RemoveUserFriend(friendlistowner, friend);
  564. }
  565. public List<FriendListItem> GetUserFriendList(LLUUID friendlistowner)
  566. {
  567. return m_commsProvider.GetUserFriendList(friendlistowner);
  568. }
  569. public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  570. {
  571. return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
  572. }
  573. public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(LLUUID queryID, string query)
  574. {
  575. return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query);
  576. }
  577. }
  578. }