SceneCommunicationService.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  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 OpenMetaverse;
  33. using OpenMetaverse.StructuredData;
  34. using log4net;
  35. using OpenSim.Framework;
  36. using OpenSim.Framework.Communications;
  37. using OpenSim.Framework.Communications.Cache;
  38. using OpenSim.Framework.Communications.Capabilities;
  39. using OpenSim.Region.Framework.Interfaces;
  40. using OSD = OpenMetaverse.StructuredData.OSD;
  41. namespace OpenSim.Region.Framework.Scenes
  42. {
  43. public delegate void KiPrimitiveDelegate(uint localID);
  44. public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
  45. public class SceneCommunicationService //one instance per region
  46. {
  47. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  48. protected CommunicationsManager m_commsProvider;
  49. protected IInterregionCommsOut m_interregionCommsOut;
  50. protected RegionInfo m_regionInfo;
  51. protected RegionCommsListener regionCommsHost;
  52. protected List<UUID> m_agentsInTransit;
  53. public event AgentCrossing OnAvatarCrossingIntoRegion;
  54. public event ExpectUserDelegate OnExpectUser;
  55. public event ExpectPrimDelegate OnExpectPrim;
  56. public event CloseAgentConnection OnCloseAgentConnection;
  57. public event PrimCrossing OnPrimCrossingIntoRegion;
  58. public event RegionUp OnRegionUp;
  59. public event ChildAgentUpdate OnChildAgentUpdate;
  60. //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
  61. public event LogOffUser OnLogOffUser;
  62. public event GetLandData OnGetLandData;
  63. private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
  64. private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
  65. private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
  66. private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
  67. private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
  68. private RegionUp handlerRegionUp = null; // OnRegionUp;
  69. private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
  70. //private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
  71. private LogOffUser handlerLogOffUser = null;
  72. private GetLandData handlerGetLandData = null; // OnGetLandData
  73. public KiPrimitiveDelegate KiPrimitive;
  74. public SceneCommunicationService(CommunicationsManager commsMan)
  75. {
  76. m_commsProvider = commsMan;
  77. m_agentsInTransit = new List<UUID>();
  78. }
  79. /// <summary>
  80. /// Register a region with the grid
  81. /// </summary>
  82. /// <param name="regionInfos"></param>
  83. /// <exception cref="System.Exception">Thrown if region registration fails.</exception>
  84. public void RegisterRegion(IInterregionCommsOut comms_out, RegionInfo regionInfos)
  85. {
  86. m_interregionCommsOut = comms_out;
  87. m_regionInfo = regionInfos;
  88. m_commsProvider.GridService.gdebugRegionName = regionInfos.RegionName;
  89. regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo);
  90. if (regionCommsHost != null)
  91. {
  92. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
  93. regionCommsHost.debugRegionName = regionInfos.RegionName;
  94. regionCommsHost.OnExpectPrim += IncomingPrimCrossing;
  95. regionCommsHost.OnExpectUser += NewUserConnection;
  96. regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing;
  97. regionCommsHost.OnCloseAgentConnection += CloseConnection;
  98. regionCommsHost.OnRegionUp += newRegionUp;
  99. regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
  100. regionCommsHost.OnLogOffUser += GridLogOffUser;
  101. regionCommsHost.OnGetLandData += FetchLandData;
  102. }
  103. else
  104. {
  105. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
  106. }
  107. }
  108. public RegionInfo RequestClosestRegion(string name)
  109. {
  110. return m_commsProvider.GridService.RequestClosestRegion(name);
  111. }
  112. public void Close()
  113. {
  114. if (regionCommsHost != null)
  115. {
  116. regionCommsHost.OnLogOffUser -= GridLogOffUser;
  117. regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
  118. regionCommsHost.OnRegionUp -= newRegionUp;
  119. regionCommsHost.OnExpectUser -= NewUserConnection;
  120. regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
  121. regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
  122. regionCommsHost.OnCloseAgentConnection -= CloseConnection;
  123. regionCommsHost.OnGetLandData -= FetchLandData;
  124. try
  125. {
  126. m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
  127. }
  128. catch (Exception e)
  129. {
  130. m_log.ErrorFormat(
  131. "[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing",
  132. m_regionInfo.RegionName, e);
  133. }
  134. regionCommsHost = null;
  135. }
  136. }
  137. #region CommsManager Event handlers
  138. /// <summary>
  139. ///
  140. /// </summary>
  141. /// <param name="regionHandle"></param>
  142. /// <param name="agent"></param>
  143. ///
  144. protected void NewUserConnection(AgentCircuitData agent)
  145. {
  146. handlerExpectUser = OnExpectUser;
  147. if (handlerExpectUser != null)
  148. {
  149. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
  150. handlerExpectUser(agent);
  151. }
  152. }
  153. protected void GridLogOffUser(UUID AgentID, UUID RegionSecret, string message)
  154. {
  155. handlerLogOffUser = OnLogOffUser;
  156. if (handlerLogOffUser != null)
  157. {
  158. handlerLogOffUser(AgentID, RegionSecret, message);
  159. }
  160. }
  161. protected bool newRegionUp(RegionInfo region)
  162. {
  163. handlerRegionUp = OnRegionUp;
  164. if (handlerRegionUp != null)
  165. {
  166. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
  167. handlerRegionUp(region);
  168. }
  169. return true;
  170. }
  171. protected bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData)
  172. {
  173. handlerChildAgentUpdate = OnChildAgentUpdate;
  174. if (handlerChildAgentUpdate != null)
  175. handlerChildAgentUpdate(cAgentData);
  176. return true;
  177. }
  178. protected void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
  179. {
  180. handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
  181. if (handlerAvatarCrossingIntoRegion != null)
  182. {
  183. handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
  184. }
  185. }
  186. protected bool IncomingPrimCrossing(UUID primID, String objXMLData, int XMLMethod)
  187. {
  188. handlerExpectPrim = OnExpectPrim;
  189. if (handlerExpectPrim != null)
  190. {
  191. return handlerExpectPrim(primID, objXMLData, XMLMethod);
  192. }
  193. else
  194. {
  195. return false;
  196. }
  197. }
  198. protected void PrimCrossing(UUID primID, Vector3 position, bool isPhysical)
  199. {
  200. handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion;
  201. if (handlerPrimCrossingIntoRegion != null)
  202. {
  203. handlerPrimCrossingIntoRegion(primID, position, isPhysical);
  204. }
  205. }
  206. protected bool CloseConnection(UUID agentID)
  207. {
  208. m_log.Debug("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID);
  209. handlerCloseAgentConnection = OnCloseAgentConnection;
  210. if (handlerCloseAgentConnection != null)
  211. {
  212. return handlerCloseAgentConnection(agentID);
  213. }
  214. return false;
  215. }
  216. protected LandData FetchLandData(uint x, uint y)
  217. {
  218. handlerGetLandData = OnGetLandData;
  219. if (handlerGetLandData != null)
  220. {
  221. return handlerGetLandData(x, y);
  222. }
  223. return null;
  224. }
  225. #endregion
  226. #region Inform Client of Neighbours
  227. private delegate void InformClientOfNeighbourDelegate(
  228. ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint, bool newAgent);
  229. private void InformClientOfNeighbourCompleted(IAsyncResult iar)
  230. {
  231. InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState;
  232. icon.EndInvoke(iar);
  233. }
  234. /// <summary>
  235. /// Async component for informing client of which neighbours exist
  236. /// </summary>
  237. /// <remarks>
  238. /// This needs to run asynchronesously, as a network timeout may block the thread for a long while
  239. /// </remarks>
  240. /// <param name="remoteClient"></param>
  241. /// <param name="a"></param>
  242. /// <param name="regionHandle"></param>
  243. /// <param name="endPoint"></param>
  244. private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg,
  245. IPEndPoint endPoint, bool newAgent)
  246. {
  247. // Let's wait just a little to give time to originating regions to catch up with closing child agents
  248. // after a cross here
  249. Thread.Sleep(500);
  250. uint x, y;
  251. Utils.LongToUInts(reg.RegionHandle, out x, out y);
  252. x = x / Constants.RegionSize;
  253. y = y / Constants.RegionSize;
  254. m_log.Info("[INTERGRID]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
  255. string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  256. + "/CAPS/" + a.CapsPath + "0000/";
  257. //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
  258. bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a);
  259. if (regionAccepted && newAgent)
  260. {
  261. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  262. if (eq != null)
  263. {
  264. eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);
  265. eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
  266. m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}",
  267. capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName);
  268. }
  269. else
  270. {
  271. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  272. // TODO: make Event Queue disablable!
  273. }
  274. m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString());
  275. }
  276. }
  277. public void RequestNeighbors(RegionInfo region)
  278. {
  279. // List<SimpleRegionInfo> neighbours =
  280. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  281. //IPEndPoint blah = new IPEndPoint();
  282. //blah.Address = region.RemotingAddress;
  283. //blah.Port = region.RemotingPort;
  284. }
  285. /// <summary>
  286. /// This informs all neighboring regions about agent "avatar".
  287. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  288. /// </summary>
  289. public void EnableNeighbourChildAgents(ScenePresence avatar, List<RegionInfo> lstneighbours)
  290. {
  291. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  292. //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  293. for (int i = 0; i < lstneighbours.Count; i++)
  294. {
  295. // We don't want to keep sending to regions that consistently fail on comms.
  296. if (!(lstneighbours[i].commFailTF))
  297. {
  298. neighbours.Add(new SimpleRegionInfo(lstneighbours[i]));
  299. }
  300. }
  301. // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
  302. // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
  303. neighbours =
  304. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  305. /// We need to find the difference between the new regions where there are no child agents
  306. /// and the regions where there are already child agents. We only send notification to the former.
  307. List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
  308. neighbourHandles.Add(avatar.Scene.RegionInfo.RegionHandle); // add this region too
  309. List<ulong> previousRegionNeighbourHandles
  310. = new List<ulong>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID).Keys);
  311. List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  312. List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  313. //Dump("Current Neighbors", neighbourHandles);
  314. //Dump("Previous Neighbours", previousRegionNeighbourHandles);
  315. //Dump("New Neighbours", newRegions);
  316. //Dump("Old Neighbours", oldRegions);
  317. /// Update the scene presence's known regions here on this region
  318. avatar.DropOldNeighbours(oldRegions);
  319. /// Collect as many seeds as possible
  320. Dictionary<ulong, string> seeds
  321. = new Dictionary<ulong, string>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID));
  322. //m_log.Debug(" !!! No. of seeds: " + seeds.Count);
  323. if (!seeds.ContainsKey(avatar.Scene.RegionInfo.RegionHandle))
  324. seeds.Add(avatar.Scene.RegionInfo.RegionHandle, avatar.ControllingClient.RequestClientInfo().CapsPath);
  325. /// Create the necessary child agents
  326. List<AgentCircuitData> cagents = new List<AgentCircuitData>();
  327. foreach (SimpleRegionInfo neighbour in neighbours)
  328. {
  329. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  330. {
  331. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  332. agent.BaseFolder = UUID.Zero;
  333. agent.InventoryFolder = UUID.Zero;
  334. agent.startpos = new Vector3(128, 128, 70);
  335. agent.child = true;
  336. if (newRegions.Contains(neighbour.RegionHandle))
  337. {
  338. agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
  339. avatar.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
  340. seeds.Add(neighbour.RegionHandle, agent.CapsPath);
  341. }
  342. else
  343. agent.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, neighbour.RegionHandle);
  344. cagents.Add(agent);
  345. }
  346. }
  347. /// Update all child agent with everyone's seeds
  348. foreach (AgentCircuitData a in cagents)
  349. {
  350. a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
  351. }
  352. // These two are the same thing!
  353. avatar.Scene.CapsModule.SetChildrenSeed(avatar.UUID, seeds);
  354. avatar.KnownRegions = seeds;
  355. //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
  356. //avatar.DumpKnownRegions();
  357. bool newAgent = false;
  358. int count = 0;
  359. foreach (SimpleRegionInfo neighbour in neighbours)
  360. {
  361. // Don't do it if there's already an agent in that region
  362. if (newRegions.Contains(neighbour.RegionHandle))
  363. newAgent = true;
  364. else
  365. newAgent = false;
  366. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  367. {
  368. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  369. try
  370. {
  371. d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
  372. InformClientOfNeighbourCompleted,
  373. d);
  374. }
  375. catch (Exception e)
  376. {
  377. m_log.ErrorFormat(
  378. "[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
  379. neighbour.ExternalHostName,
  380. neighbour.RegionHandle,
  381. neighbour.RegionLocX,
  382. neighbour.RegionLocY,
  383. e);
  384. // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
  385. // since I don't know what will happen if we just let the client continue
  386. // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
  387. // throw e;
  388. }
  389. }
  390. count++;
  391. }
  392. }
  393. /// <summary>
  394. /// This informs a single neighboring region about agent "avatar".
  395. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  396. /// </summary>
  397. public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region)
  398. {
  399. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  400. agent.BaseFolder = UUID.Zero;
  401. agent.InventoryFolder = UUID.Zero;
  402. agent.startpos = new Vector3(128, 128, 70);
  403. agent.child = true;
  404. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  405. d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint, true,
  406. InformClientOfNeighbourCompleted,
  407. d);
  408. }
  409. #endregion
  410. public delegate void InformNeighbourThatRegionUpDelegate(RegionInfo region, ulong regionhandle);
  411. private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
  412. {
  413. InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
  414. icon.EndInvoke(iar);
  415. }
  416. /// <summary>
  417. /// Asynchronous call to information neighbouring regions that this region is up
  418. /// </summary>
  419. /// <param name="region"></param>
  420. /// <param name="regionhandle"></param>
  421. private void InformNeighboursThatRegionIsUpAsync(RegionInfo region, ulong regionhandle)
  422. {
  423. m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here");
  424. //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
  425. //bool regionAccepted =
  426. // m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle);
  427. bool regionAccepted = m_interregionCommsOut.SendHelloNeighbour(regionhandle, region);
  428. if (regionAccepted)
  429. {
  430. m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here");
  431. handlerRegionUp = OnRegionUp;
  432. // yes, we're notifying ourselves.
  433. if (handlerRegionUp != null)
  434. handlerRegionUp(region);
  435. }
  436. else
  437. {
  438. m_log.Warn("[INTERGRID]: Failed to inform neighbors that I'm here.");
  439. }
  440. }
  441. /// <summary>
  442. /// Called by scene when region is initialized (not always when it's listening for agents)
  443. /// This is an inter-region message that informs the surrounding neighbors that the sim is up.
  444. /// </summary>
  445. public void InformNeighborsThatRegionisUp(RegionInfo region)
  446. {
  447. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
  448. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  449. // This stays uncached because we don't already know about our neighbors at this point.
  450. neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  451. if (neighbours != null)
  452. {
  453. for (int i = 0; i < neighbours.Count; i++)
  454. {
  455. InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
  456. d.BeginInvoke(region, neighbours[i].RegionHandle,
  457. InformNeighborsThatRegionisUpCompleted,
  458. d);
  459. }
  460. }
  461. //bool val = m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region));
  462. }
  463. public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, ulong regionHandle);
  464. /// <summary>
  465. /// This informs all neighboring regions about the settings of it's child agent.
  466. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  467. ///
  468. /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
  469. ///
  470. /// </summary>
  471. private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, ulong regionHandle)
  472. {
  473. //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
  474. try
  475. {
  476. //m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
  477. m_interregionCommsOut.SendChildAgentUpdate(regionHandle, cAgentData);
  478. }
  479. catch
  480. {
  481. // Ignore; we did our best
  482. }
  483. //if (regionAccepted)
  484. //{
  485. // //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
  486. //}
  487. //else
  488. //{
  489. // //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
  490. //}
  491. }
  492. private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
  493. {
  494. SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
  495. icon.EndInvoke(iar);
  496. }
  497. public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
  498. {
  499. // This assumes that we know what our neighbors are.
  500. try
  501. {
  502. foreach (ulong regionHandle in presence.KnownChildRegionHandles)
  503. {
  504. if (regionHandle != m_regionInfo.RegionHandle)
  505. {
  506. SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
  507. d.BeginInvoke(cAgentData, regionHandle,
  508. SendChildAgentDataUpdateCompleted,
  509. d);
  510. }
  511. }
  512. }
  513. catch (InvalidOperationException)
  514. {
  515. // We're ignoring a collection was modified error because this data gets old and outdated fast.
  516. }
  517. }
  518. public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
  519. /// <summary>
  520. /// This Closes child agents on neighboring regions
  521. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  522. /// </summary>
  523. protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
  524. {
  525. m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
  526. // let's do our best, but there's not much we can do if the neighbour doesn't accept.
  527. //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
  528. m_interregionCommsOut.SendCloseAgent(regionHandle, agentID);
  529. }
  530. private void SendCloseChildAgentCompleted(IAsyncResult iar)
  531. {
  532. SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
  533. icon.EndInvoke(iar);
  534. }
  535. public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
  536. {
  537. foreach (ulong handle in regionslst)
  538. {
  539. SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
  540. d.BeginInvoke(agentID, handle,
  541. SendCloseChildAgentCompleted,
  542. d);
  543. }
  544. }
  545. /// <summary>
  546. /// Helper function to request neighbors from grid-comms
  547. /// </summary>
  548. /// <param name="regionHandle"></param>
  549. /// <returns></returns>
  550. public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
  551. {
  552. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
  553. return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle);
  554. }
  555. /// <summary>
  556. /// Helper function to request neighbors from grid-comms
  557. /// </summary>
  558. /// <param name="regionID"></param>
  559. /// <returns></returns>
  560. public virtual RegionInfo RequestNeighbouringRegionInfo(UUID regionID)
  561. {
  562. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionID);
  563. return m_commsProvider.GridService.RequestNeighbourInfo(regionID);
  564. }
  565. /// <summary>
  566. /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
  567. /// </summary>
  568. /// <param name="minX"></param>
  569. /// <param name="minY"></param>
  570. /// <param name="maxX"></param>
  571. /// <param name="maxY"></param>
  572. public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
  573. {
  574. List<MapBlockData> mapBlocks;
  575. mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4);
  576. remoteClient.SendMapBlock(mapBlocks, 0);
  577. }
  578. /// <summary>
  579. /// Try to teleport an agent to a new region.
  580. /// </summary>
  581. /// <param name="remoteClient"></param>
  582. /// <param name="RegionHandle"></param>
  583. /// <param name="position"></param>
  584. /// <param name="lookAt"></param>
  585. /// <param name="flags"></param>
  586. public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
  587. Vector3 lookAt, uint teleportFlags)
  588. {
  589. if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
  590. return;
  591. bool destRegionUp = true;
  592. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  593. // Reset animations; the viewer does that in teleports.
  594. avatar.ResetAnimations();
  595. if (regionHandle == m_regionInfo.RegionHandle)
  596. {
  597. m_log.DebugFormat(
  598. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
  599. position, m_regionInfo.RegionName);
  600. // Teleport within the same region
  601. if (position.X < 0 || position.X > Constants.RegionSize || position.Y < 0 || position.Y > Constants.RegionSize || position.Z < 0)
  602. {
  603. Vector3 emergencyPos = new Vector3(128, 128, 128);
  604. m_log.WarnFormat(
  605. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
  606. position, avatar.Name, avatar.UUID, emergencyPos);
  607. position = emergencyPos;
  608. }
  609. // TODO: Get proper AVG Height
  610. float localAVHeight = 1.56f;
  611. float posZLimit = (float)avatar.Scene.GetLandHeight((int)position.X, (int)position.Y);
  612. float newPosZ = posZLimit + localAVHeight;
  613. if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
  614. {
  615. position.Z = newPosZ;
  616. }
  617. // Only send this if the event queue is null
  618. if (eq == null)
  619. avatar.ControllingClient.SendTeleportLocationStart();
  620. avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
  621. avatar.Teleport(position);
  622. }
  623. else
  624. {
  625. RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
  626. if (reg != null)
  627. {
  628. m_log.DebugFormat(
  629. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}",
  630. position, reg.RegionName);
  631. if (eq == null)
  632. avatar.ControllingClient.SendTeleportLocationStart();
  633. // Let's do DNS resolution only once in this process, please!
  634. // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
  635. // it's actually doing a lot of work.
  636. IPEndPoint endPoint = reg.ExternalEndPoint;
  637. if (endPoint.Address == null)
  638. {
  639. // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
  640. destRegionUp = false;
  641. }
  642. if (destRegionUp)
  643. {
  644. uint newRegionX = (uint)(reg.RegionHandle >> 40);
  645. uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
  646. uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
  647. uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
  648. // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
  649. // both regions
  650. if (avatar.ParentID != (uint)0)
  651. avatar.StandUp();
  652. if (!avatar.ValidateAttachments())
  653. {
  654. avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
  655. return;
  656. }
  657. // the avatar.Close below will clear the child region list. We need this below for (possibly)
  658. // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
  659. //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
  660. // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
  661. // failure at this point (unlike a border crossing failure). So perhaps this can never fail
  662. // once we reach here...
  663. //avatar.Scene.RemoveCapsHandler(avatar.UUID);
  664. string capsPath = String.Empty;
  665. AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
  666. agentCircuit.BaseFolder = UUID.Zero;
  667. agentCircuit.InventoryFolder = UUID.Zero;
  668. agentCircuit.startpos = position;
  669. agentCircuit.child = true;
  670. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  671. {
  672. // brand new agent, let's create a new caps seed
  673. agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
  674. }
  675. // Let's create an agent there if one doesn't exist yet.
  676. //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
  677. if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit))
  678. {
  679. avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
  680. return;
  681. }
  682. // OK, it got this agent. Let's close some child agents
  683. avatar.CloseChildAgents(newRegionX, newRegionY);
  684. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  685. {
  686. capsPath
  687. = "http://"
  688. + reg.ExternalHostName
  689. + ":"
  690. + reg.HttpPort
  691. + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
  692. if (eq != null)
  693. {
  694. eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);
  695. // ES makes the client send a UseCircuitCode message to the destination,
  696. // which triggers a bunch of things there.
  697. // So let's wait
  698. Thread.Sleep(2000);
  699. eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
  700. }
  701. else
  702. {
  703. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  704. }
  705. }
  706. else
  707. {
  708. agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
  709. capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  710. + "/CAPS/" + agentCircuit.CapsPath + "0000/";
  711. }
  712. // Expect avatar crossing is a heavy-duty function at the destination.
  713. // That is where MakeRoot is called, which fetches appearance and inventory.
  714. // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
  715. //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
  716. // position, false);
  717. //{
  718. // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
  719. // // We should close that agent we just created over at destination...
  720. // List<ulong> lst = new List<ulong>();
  721. // lst.Add(reg.RegionHandle);
  722. // SendCloseChildAgentAsync(avatar.UUID, lst);
  723. // return;
  724. //}
  725. SetInTransit(avatar.UUID);
  726. // Let's send a full update of the agent. This is a synchronous call.
  727. AgentData agent = new AgentData();
  728. avatar.CopyTo(agent);
  729. agent.Position = position;
  730. agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
  731. "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
  732. m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);
  733. m_log.DebugFormat(
  734. "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);
  735. if (eq != null)
  736. {
  737. eq.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
  738. 4, teleportFlags, capsPath, avatar.UUID);
  739. }
  740. else
  741. {
  742. avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
  743. teleportFlags, capsPath);
  744. }
  745. // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
  746. // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
  747. // that the client contacted the destination before we send the attachments and close things here.
  748. if (!WaitForCallback(avatar.UUID))
  749. {
  750. // Client never contacted destination. Let's restore everything back
  751. avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
  752. ResetFromTransit(avatar.UUID);
  753. // Yikes! We should just have a ref to scene here.
  754. avatar.Scene.InformClientOfNeighbours(avatar);
  755. // Finally, kill the agent we just created at the destination.
  756. m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);
  757. return;
  758. }
  759. // Can't go back from here
  760. if (KiPrimitive != null)
  761. {
  762. KiPrimitive(avatar.LocalId);
  763. }
  764. avatar.MakeChildAgent();
  765. // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
  766. avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);
  767. // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
  768. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  769. {
  770. Thread.Sleep(5000);
  771. avatar.Close();
  772. CloseConnection(avatar.UUID);
  773. }
  774. else
  775. // now we have a child agent in this region.
  776. avatar.Reset();
  777. // if (teleport success) // seems to be always success here
  778. // the user may change their profile information in other region,
  779. // so the userinfo in UserProfileCache is not reliable any more, delete it
  780. if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
  781. {
  782. m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
  783. m_log.DebugFormat(
  784. "[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed",
  785. avatar.UUID);
  786. }
  787. }
  788. else
  789. {
  790. avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
  791. }
  792. }
  793. else
  794. {
  795. // TP to a place that doesn't exist (anymore)
  796. // Inform the viewer about that
  797. avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
  798. // and set the map-tile to '(Offline)'
  799. uint regX, regY;
  800. Utils.LongToUInts(regionHandle, out regX, out regY);
  801. MapBlockData block = new MapBlockData();
  802. block.X = (ushort)(regX / Constants.RegionSize);
  803. block.Y = (ushort)(regY / Constants.RegionSize);
  804. block.Access = 254; // == not there
  805. List<MapBlockData> blocks = new List<MapBlockData>();
  806. blocks.Add(block);
  807. avatar.ControllingClient.SendMapBlock(blocks, 0);
  808. }
  809. }
  810. }
  811. public bool WaitForCallback(UUID id)
  812. {
  813. int count = 20;
  814. while (m_agentsInTransit.Contains(id) && count-- > 0)
  815. {
  816. //m_log.Debug(" >>> Waiting... " + count);
  817. Thread.Sleep(1000);
  818. }
  819. if (count > 0)
  820. return true;
  821. else
  822. return false;
  823. }
  824. public bool ReleaseAgent(UUID id)
  825. {
  826. //m_log.Debug(" >>> ReleaseAgent called <<< ");
  827. return ResetFromTransit(id);
  828. }
  829. public void SetInTransit(UUID id)
  830. {
  831. lock (m_agentsInTransit)
  832. {
  833. if (!m_agentsInTransit.Contains(id))
  834. m_agentsInTransit.Add(id);
  835. }
  836. }
  837. protected bool ResetFromTransit(UUID id)
  838. {
  839. lock (m_agentsInTransit)
  840. {
  841. if (m_agentsInTransit.Contains(id))
  842. {
  843. m_agentsInTransit.Remove(id);
  844. return true;
  845. }
  846. }
  847. return false;
  848. }
  849. private List<ulong> NeighbourHandles(List<SimpleRegionInfo> neighbours)
  850. {
  851. List<ulong> handles = new List<ulong>();
  852. foreach (SimpleRegionInfo reg in neighbours)
  853. {
  854. handles.Add(reg.RegionHandle);
  855. }
  856. return handles;
  857. }
  858. private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  859. {
  860. return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
  861. }
  862. // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  863. // {
  864. // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
  865. // }
  866. private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  867. {
  868. return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
  869. }
  870. public void CrossAgentToNewRegion(Scene scene, ScenePresence agent, bool isFlying)
  871. {
  872. Vector3 pos = agent.AbsolutePosition;
  873. Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
  874. uint neighbourx = m_regionInfo.RegionLocX;
  875. uint neighboury = m_regionInfo.RegionLocY;
  876. // distance to edge that will trigger crossing
  877. const float boundaryDistance = 1.7f;
  878. // distance into new region to place avatar
  879. const float enterDistance = 0.1f;
  880. if (pos.X < boundaryDistance)
  881. {
  882. neighbourx--;
  883. newpos.X = Constants.RegionSize - enterDistance;
  884. }
  885. else if (pos.X > Constants.RegionSize - boundaryDistance)
  886. {
  887. neighbourx++;
  888. newpos.X = enterDistance;
  889. }
  890. if (pos.Y < boundaryDistance)
  891. {
  892. neighboury--;
  893. newpos.Y = Constants.RegionSize - enterDistance;
  894. }
  895. else if (pos.Y > Constants.RegionSize - boundaryDistance)
  896. {
  897. neighboury++;
  898. newpos.Y = enterDistance;
  899. }
  900. CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
  901. d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d);
  902. }
  903. public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying);
  904. /// <summary>
  905. /// This Closes child agents on neighboring regions
  906. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  907. /// </summary>
  908. protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying)
  909. {
  910. m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
  911. ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
  912. SimpleRegionInfo neighbourRegion = RequestNeighbouringRegionInfo(neighbourHandle);
  913. if (neighbourRegion != null && agent.ValidateAttachments())
  914. {
  915. pos = pos + (agent.Velocity);
  916. CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
  917. if (userInfo != null)
  918. {
  919. userInfo.DropInventory();
  920. }
  921. else
  922. {
  923. m_log.WarnFormat("[SCENE COMM]: No cached user info found for {0} {1} on leaving region {2}",
  924. agent.Name, agent.UUID, agent.Scene.RegionInfo.RegionName);
  925. }
  926. //bool crossingSuccessful =
  927. // CrossToNeighbouringRegion(neighbourHandle, agent.ControllingClient.AgentId, pos,
  928. //isFlying);
  929. SetInTransit(agent.UUID);
  930. AgentData cAgent = new AgentData();
  931. agent.CopyTo(cAgent);
  932. cAgent.Position = pos;
  933. if (isFlying)
  934. cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
  935. cAgent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
  936. "/agent/" + agent.UUID.ToString() + "/" + agent.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
  937. m_interregionCommsOut.SendChildAgentUpdate(neighbourHandle, cAgent);
  938. // Next, let's close the child agent connections that are too far away.
  939. agent.CloseChildAgents(neighbourx, neighboury);
  940. //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
  941. agent.ControllingClient.RequestClientInfo();
  942. //m_log.Debug("BEFORE CROSS");
  943. //Scene.DumpChildrenSeeds(UUID);
  944. //DumpKnownRegions();
  945. string agentcaps;
  946. if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
  947. {
  948. m_log.ErrorFormat("[SCENE COMM]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
  949. neighbourRegion.RegionHandle);
  950. return agent;
  951. }
  952. // TODO Should construct this behind a method
  953. string capsPath =
  954. "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
  955. + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
  956. m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
  957. IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
  958. if (eq != null)
  959. {
  960. eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
  961. capsPath, agent.UUID, agent.ControllingClient.SessionId);
  962. }
  963. else
  964. {
  965. agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
  966. capsPath);
  967. }
  968. if (!WaitForCallback(agent.UUID))
  969. {
  970. ResetFromTransit(agent.UUID);
  971. // Yikes! We should just have a ref to scene here.
  972. agent.Scene.InformClientOfNeighbours(agent);
  973. return agent;
  974. }
  975. agent.MakeChildAgent();
  976. // now we have a child agent in this region. Request all interesting data about other (root) agents
  977. agent.SendInitialFullUpdateToAllClients();
  978. agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true);
  979. // m_scene.SendKillObject(m_localId);
  980. agent.Scene.NotifyMyCoarseLocationChange();
  981. // the user may change their profile information in other region,
  982. // so the userinfo in UserProfileCache is not reliable any more, delete it
  983. if (agent.Scene.NeedSceneCacheClear(agent.UUID))
  984. {
  985. agent.Scene.CommsManager.UserProfileCacheService.RemoveUser(agent.UUID);
  986. m_log.DebugFormat(
  987. "[SCENE COMM]: User {0} is going to another region, profile cache removed", agent.UUID);
  988. }
  989. }
  990. //m_log.Debug("AFTER CROSS");
  991. //Scene.DumpChildrenSeeds(UUID);
  992. //DumpKnownRegions();
  993. return agent;
  994. }
  995. private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
  996. {
  997. CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
  998. ScenePresence agent = icon.EndInvoke(iar);
  999. // If the cross was successful, this agent is a child agent
  1000. if (agent.IsChildAgent)
  1001. {
  1002. agent.Reset();
  1003. }
  1004. else // Not successful
  1005. {
  1006. CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
  1007. if (userInfo != null)
  1008. {
  1009. userInfo.FetchInventory();
  1010. }
  1011. agent.RestoreInCurrentScene();
  1012. }
  1013. // In any case
  1014. agent.NotInTransit();
  1015. //m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
  1016. }
  1017. public Dictionary<string, string> GetGridSettings()
  1018. {
  1019. return m_commsProvider.GridService.GetGridSettings();
  1020. }
  1021. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
  1022. {
  1023. m_commsProvider.LogOffUser(userid, regionid, regionhandle, position, lookat);
  1024. }
  1025. // deprecated as of 2008-08-27
  1026. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
  1027. {
  1028. m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
  1029. }
  1030. public void ClearUserAgent(UUID avatarID)
  1031. {
  1032. m_commsProvider.UserService.ClearUserAgent(avatarID);
  1033. }
  1034. public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
  1035. {
  1036. m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms);
  1037. }
  1038. public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
  1039. {
  1040. m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms);
  1041. }
  1042. public void RemoveUserFriend(UUID friendlistowner, UUID friend)
  1043. {
  1044. m_commsProvider.RemoveUserFriend(friendlistowner, friend);
  1045. }
  1046. public List<FriendListItem> GetUserFriendList(UUID friendlistowner)
  1047. {
  1048. return m_commsProvider.GetUserFriendList(friendlistowner);
  1049. }
  1050. public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  1051. {
  1052. return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
  1053. }
  1054. public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
  1055. {
  1056. return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query);
  1057. }
  1058. public List<RegionInfo> RequestNamedRegions(string name, int maxNumber)
  1059. {
  1060. return m_commsProvider.GridService.RequestNamedRegions(name, maxNumber);
  1061. }
  1062. // private void Dump(string msg, List<ulong> handles)
  1063. // {
  1064. // m_log.Info"-------------- HANDLE DUMP ({0}) ---------", msg);
  1065. // foreach (ulong handle in handles)
  1066. // {
  1067. // uint x, y;
  1068. // Utils.LongToUInts(handle, out x, out y);
  1069. // x = x / Constants.RegionSize;
  1070. // y = y / Constants.RegionSize;
  1071. // m_log.Info("({0}, {1})", x, y);
  1072. // }
  1073. // }
  1074. }
  1075. }