aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
diff options
context:
space:
mode:
authorDiva Canto2010-01-15 17:14:48 -0800
committerDiva Canto2010-01-15 17:14:48 -0800
commit4ac3c0e81b8760ef31f741cd55e703eee86b93b7 (patch)
tree18565d8b20669ccdc45e3ef02d59cfd1eabaa297 /OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
parentMerge branch 'presence-refactor' of ssh://diva@opensimulator.org/var/git/open... (diff)
downloadopensim-SC_OLD-4ac3c0e81b8760ef31f741cd55e703eee86b93b7.zip
opensim-SC_OLD-4ac3c0e81b8760ef31f741cd55e703eee86b93b7.tar.gz
opensim-SC_OLD-4ac3c0e81b8760ef31f741cd55e703eee86b93b7.tar.bz2
opensim-SC_OLD-4ac3c0e81b8760ef31f741cd55e703eee86b93b7.tar.xz
Renamed IAgentTransferModule to IEntityTransferModule -- accounts for objects too.
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1201
1 files changed, 1201 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
new file mode 100644
index 0000000..af004b0
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -0,0 +1,1201 @@
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 OpenSimulator 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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using System.Threading;
33
34using OpenSim.Framework;
35using OpenSim.Framework.Capabilities;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40
41using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42
43using OpenMetaverse;
44using log4net;
45using Nini.Config;
46
47namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
48{
49 public class AgentTransferModule : ISharedRegionModule, IEntityTransferModule
50 {
51 #region ISharedRegionModule
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private bool m_Enabled = false;
55 protected Scene m_aScene;
56 protected List<UUID> m_agentsInTransit;
57
58 public Type ReplaceableInterface
59 {
60 get { return null; }
61 }
62
63 public string Name
64 {
65 get { return "AgentTransferModule"; }
66 }
67
68 public virtual void Initialise(IConfigSource source)
69 {
70 IConfig moduleConfig = source.Configs["Modules"];
71 if (moduleConfig != null)
72 {
73 string name = moduleConfig.GetString("AgentTransferModule", "");
74 if (name == Name)
75 {
76 m_agentsInTransit = new List<UUID>();
77 m_Enabled = true;
78 m_log.Info("[AGENT TRANSFER MODULE]: Enabled.");
79 }
80 }
81 }
82
83 public virtual void PostInitialise()
84 {
85 }
86
87 public virtual void AddRegion(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91
92 if (m_aScene == null)
93 m_aScene = scene;
94
95 scene.RegisterModuleInterface<IEntityTransferModule>(this);
96 }
97
98 public virtual void Close()
99 {
100 if (!m_Enabled)
101 return;
102 }
103
104
105 public virtual void RemoveRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109 if (scene == m_aScene)
110 m_aScene = null;
111 }
112
113 public virtual void RegionLoaded(Scene scene)
114 {
115 if (!m_Enabled)
116 return;
117
118 }
119
120
121 #endregion
122
123 #region Teleports
124
125 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
126 {
127 if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
128 return;
129
130 bool destRegionUp = true;
131
132 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
133
134 // Reset animations; the viewer does that in teleports.
135 sp.Animator.ResetAnimations();
136
137 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
138 {
139 m_log.DebugFormat(
140 "[AGENT TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
141 position, sp.Scene.RegionInfo.RegionName);
142
143 // Teleport within the same region
144 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
145 {
146 Vector3 emergencyPos = new Vector3(128, 128, 128);
147
148 m_log.WarnFormat(
149 "[AGENT TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
150 position, sp.Name, sp.UUID, emergencyPos);
151 position = emergencyPos;
152 }
153
154 // TODO: Get proper AVG Height
155 float localAVHeight = 1.56f;
156 float posZLimit = 22;
157
158 // TODO: Check other Scene HeightField
159 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
160 {
161 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
162 }
163
164 float newPosZ = posZLimit + localAVHeight;
165 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
166 {
167 position.Z = newPosZ;
168 }
169
170 // Only send this if the event queue is null
171 if (eq == null)
172 sp.ControllingClient.SendTeleportLocationStart();
173
174 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
175 sp.Teleport(position);
176 }
177 else
178 {
179 uint x = 0, y = 0;
180 Utils.LongToUInts(regionHandle, out x, out y);
181 GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
182
183 if (reg != null)
184 {
185 m_log.DebugFormat(
186 "[AGENT TRANSFER MODULE]: RequestTeleportToLocation to {0} in {1}",
187 position, reg.RegionName);
188
189 uint newRegionX = (uint)(reg.RegionHandle >> 40);
190 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
191 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
192 uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
193
194 ulong destinationHandle = GetRegionHandle(reg);
195 GridRegion finalDestination = GetFinalDestination(reg);
196
197 if (eq == null)
198 sp.ControllingClient.SendTeleportLocationStart();
199
200 // Let's do DNS resolution only once in this process, please!
201 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
202 // it's actually doing a lot of work.
203 IPEndPoint endPoint = reg.ExternalEndPoint;
204 if (endPoint.Address == null)
205 {
206 // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
207 destRegionUp = false;
208 }
209
210 if (destRegionUp)
211 {
212 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
213 // both regions
214 if (sp.ParentID != (uint)0)
215 sp.StandUp();
216
217 if (!sp.ValidateAttachments())
218 {
219 sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
220 return;
221 }
222
223 // the avatar.Close below will clear the child region list. We need this below for (possibly)
224 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
225 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
226 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
227 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
228 // once we reach here...
229 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
230
231 string capsPath = String.Empty;
232 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
233 agentCircuit.BaseFolder = UUID.Zero;
234 agentCircuit.InventoryFolder = UUID.Zero;
235 agentCircuit.startpos = position;
236 agentCircuit.child = true;
237 agentCircuit.Appearance = sp.Appearance;
238
239 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
240 {
241 // brand new agent, let's create a new caps seed
242 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
243 }
244
245 string reason = String.Empty;
246
247 // Let's create an agent there if one doesn't exist yet.
248 if (!m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason))
249 {
250 sp.ControllingClient.SendTeleportFailed(String.Format("Destination is not accepting teleports: {0}",
251 reason));
252 return;
253 }
254
255 // OK, it got this agent. Let's close some child agents
256 sp.CloseChildAgents(newRegionX, newRegionY);
257
258 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
259 {
260 #region IP Translation for NAT
261 IClientIPEndpoint ipepClient;
262 if (sp.ClientView.TryGet(out ipepClient))
263 {
264 capsPath
265 = "http://"
266 + NetworkUtil.GetHostFor(ipepClient.EndPoint, reg.ExternalHostName)
267 + ":"
268 + reg.HttpPort
269 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
270 }
271 else
272 {
273 capsPath
274 = "http://"
275 + reg.ExternalHostName
276 + ":"
277 + reg.HttpPort
278 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
279 }
280 #endregion
281
282 if (eq != null)
283 {
284 #region IP Translation for NAT
285 // Uses ipepClient above
286 if (sp.ClientView.TryGet(out ipepClient))
287 {
288 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
289 }
290 #endregion
291
292 eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);
293
294 // ES makes the client send a UseCircuitCode message to the destination,
295 // which triggers a bunch of things there.
296 // So let's wait
297 Thread.Sleep(2000);
298
299 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
300
301 }
302 else
303 {
304 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
305 }
306 }
307 else
308 {
309 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
310 capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
311 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
312 }
313
314 // Expect avatar crossing is a heavy-duty function at the destination.
315 // That is where MakeRoot is called, which fetches appearance and inventory.
316 // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
317 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
318 // position, false);
319
320 //{
321 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
322 // // We should close that agent we just created over at destination...
323 // List<ulong> lst = new List<ulong>();
324 // lst.Add(reg.RegionHandle);
325 // SendCloseChildAgentAsync(avatar.UUID, lst);
326 // return;
327 //}
328
329 SetInTransit(sp.UUID);
330
331 // Let's send a full update of the agent. This is a synchronous call.
332 AgentData agent = new AgentData();
333 sp.CopyTo(agent);
334 agent.Position = position;
335 agent.CallbackURI = "http://" + sp.Scene.RegionInfo.ExternalHostName + ":" + sp.Scene.RegionInfo.HttpPort +
336 "/agent/" + sp.UUID.ToString() + "/" + sp.Scene.RegionInfo.RegionID.ToString() + "/release/";
337
338 m_aScene.SimulationService.UpdateAgent(reg, agent);
339
340 m_log.DebugFormat(
341 "[AGENT TRANSFER MODULE]: Sending new AGENT TRANSFER MODULE seed url {0} to client {1}", capsPath, sp.UUID);
342
343
344 if (eq != null)
345 {
346 eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
347 0, teleportFlags, capsPath, sp.UUID);
348 }
349 else
350 {
351 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
352 teleportFlags, capsPath);
353 }
354
355 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
356 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
357 // that the client contacted the destination before we send the attachments and close things here.
358 if (!WaitForCallback(sp.UUID))
359 {
360 // Client never contacted destination. Let's restore everything back
361 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
362
363 ResetFromTransit(sp.UUID);
364
365 // Yikes! We should just have a ref to scene here.
366 //sp.Scene.InformClientOfNeighbours(sp);
367 EnableChildAgents(sp);
368
369 // Finally, kill the agent we just created at the destination.
370 m_aScene.SimulationService.CloseAgent(reg, sp.UUID);
371
372 return;
373 }
374
375 KillEntity(sp.Scene, sp.LocalId);
376
377 sp.MakeChildAgent();
378
379 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
380 sp.CrossAttachmentsIntoNewRegion(reg, true);
381
382 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
383
384 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
385 {
386 Thread.Sleep(5000);
387 sp.Close();
388 sp.Scene.IncomingCloseAgent(sp.UUID);
389 }
390 else
391 // now we have a child agent in this region.
392 sp.Reset();
393
394
395 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
396 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
397 {
398 m_log.DebugFormat(
399 "[AGENT TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
400 sp.UUID);
401 }
402 }
403 else
404 {
405 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
406 }
407 }
408 else
409 {
410 // TP to a place that doesn't exist (anymore)
411 // Inform the viewer about that
412 sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
413
414 // and set the map-tile to '(Offline)'
415 uint regX, regY;
416 Utils.LongToUInts(regionHandle, out regX, out regY);
417
418 MapBlockData block = new MapBlockData();
419 block.X = (ushort)(regX / Constants.RegionSize);
420 block.Y = (ushort)(regY / Constants.RegionSize);
421 block.Access = 254; // == not there
422
423 List<MapBlockData> blocks = new List<MapBlockData>();
424 blocks.Add(block);
425 sp.ControllingClient.SendMapBlock(blocks, 0);
426 }
427 }
428 }
429
430 protected void KillEntity(Scene scene, uint localID)
431 {
432 scene.SendKillObject(localID);
433 }
434
435 protected virtual ulong GetRegionHandle(GridRegion region)
436 {
437 return region.RegionHandle;
438 }
439
440 protected virtual GridRegion GetFinalDestination(GridRegion region)
441 {
442 return region;
443 }
444
445 protected virtual bool NeedsNewAgent(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
446 {
447 return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY);
448 }
449
450 protected virtual bool NeedsClosing(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
451 {
452 return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY);
453 }
454
455 protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
456 {
457
458 if (s.TestBorderCross(pos, Cardinals.N))
459 return true;
460 if (s.TestBorderCross(pos, Cardinals.S))
461 return true;
462 if (s.TestBorderCross(pos, Cardinals.E))
463 return true;
464 if (s.TestBorderCross(pos, Cardinals.W))
465 return true;
466
467 return false;
468 }
469
470
471 #endregion
472
473 #region Enable Child Agent
474 /// <summary>
475 /// This informs a single neighboring region about agent "avatar".
476 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
477 /// </summary>
478 public void EnableChildAgent(ScenePresence sp, GridRegion region)
479 {
480 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
481 agent.BaseFolder = UUID.Zero;
482 agent.InventoryFolder = UUID.Zero;
483 agent.startpos = new Vector3(128, 128, 70);
484 agent.child = true;
485 agent.Appearance = sp.Appearance;
486
487 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
488 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true,
489 InformClientOfNeighbourCompleted,
490 d);
491 }
492 #endregion
493
494 #region Crossings
495
496 public void Cross(ScenePresence agent, bool isFlying)
497 {
498 Scene scene = agent.Scene;
499 Vector3 pos = agent.AbsolutePosition;
500 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
501 uint neighbourx = scene.RegionInfo.RegionLocX;
502 uint neighboury = scene.RegionInfo.RegionLocY;
503 const float boundaryDistance = 1.7f;
504 Vector3 northCross = new Vector3(0, boundaryDistance, 0);
505 Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
506 Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
507 Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
508
509 // distance to edge that will trigger crossing
510
511
512 // distance into new region to place avatar
513 const float enterDistance = 0.5f;
514
515 if (scene.TestBorderCross(pos + westCross, Cardinals.W))
516 {
517 if (scene.TestBorderCross(pos + northCross, Cardinals.N))
518 {
519 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
520 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
521 }
522 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
523 {
524 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
525 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0)
526 {
527 neighboury--;
528 newpos.Y = Constants.RegionSize - enterDistance;
529 }
530 else
531 {
532 neighboury = b.TriggerRegionY;
533 neighbourx = b.TriggerRegionX;
534
535 Vector3 newposition = pos;
536 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
537 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
538 agent.ControllingClient.SendAgentAlertMessage(
539 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
540 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
541 return;
542 }
543 }
544
545 Border ba = scene.GetCrossedBorder(pos + westCross, Cardinals.W);
546 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0)
547 {
548 neighbourx--;
549 newpos.X = Constants.RegionSize - enterDistance;
550 }
551 else
552 {
553 neighboury = ba.TriggerRegionY;
554 neighbourx = ba.TriggerRegionX;
555
556
557 Vector3 newposition = pos;
558 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
559 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
560 agent.ControllingClient.SendAgentAlertMessage(
561 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
562 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
563
564
565 return;
566 }
567
568 }
569 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
570 {
571 Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
572 neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
573 newpos.X = enterDistance;
574
575 if (scene.TestBorderCross(pos + southCross, Cardinals.S))
576 {
577 Border ba = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
578 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0)
579 {
580 neighboury--;
581 newpos.Y = Constants.RegionSize - enterDistance;
582 }
583 else
584 {
585 neighboury = ba.TriggerRegionY;
586 neighbourx = ba.TriggerRegionX;
587 Vector3 newposition = pos;
588 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
589 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
590 agent.ControllingClient.SendAgentAlertMessage(
591 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
592 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
593 return;
594 }
595 }
596 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
597 {
598 Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
599 neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
600 newpos.Y = enterDistance;
601 }
602
603
604 }
605 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
606 {
607 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
608 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0)
609 {
610 neighboury--;
611 newpos.Y = Constants.RegionSize - enterDistance;
612 }
613 else
614 {
615 neighboury = b.TriggerRegionY;
616 neighbourx = b.TriggerRegionX;
617 Vector3 newposition = pos;
618 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
619 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
620 agent.ControllingClient.SendAgentAlertMessage(
621 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
622 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
623 return;
624 }
625 }
626 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
627 {
628
629 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
630 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
631 newpos.Y = enterDistance;
632 }
633
634 /*
635
636 if (pos.X < boundaryDistance) //West
637 {
638 neighbourx--;
639 newpos.X = Constants.RegionSize - enterDistance;
640 }
641 else if (pos.X > Constants.RegionSize - boundaryDistance) // East
642 {
643 neighbourx++;
644 newpos.X = enterDistance;
645 }
646
647 if (pos.Y < boundaryDistance) // South
648 {
649 neighboury--;
650 newpos.Y = Constants.RegionSize - enterDistance;
651 }
652 else if (pos.Y > Constants.RegionSize - boundaryDistance) // North
653 {
654 neighboury++;
655 newpos.Y = enterDistance;
656 }
657 */
658
659 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
660 d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d);
661
662 }
663
664
665 public delegate void InformClientToInitateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
666 Vector3 position,
667 Scene initiatingScene);
668
669 private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
670 {
671
672 // This assumes that we know what our neighbors are.
673
674 InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync;
675 d.BeginInvoke(agent, regionX, regionY, position, initiatingScene,
676 InformClientToInitiateTeleportToLocationCompleted,
677 d);
678 }
679
680 public void InformClientToInitiateTeleportToLocationAsync(ScenePresence agent, uint regionX, uint regionY, Vector3 position,
681 Scene initiatingScene)
682 {
683 Thread.Sleep(10000);
684 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
685 if (im != null)
686 {
687 UUID gotoLocation = Util.BuildFakeParcelID(
688 Util.UIntsToLong(
689 (regionX *
690 (uint)Constants.RegionSize),
691 (regionY *
692 (uint)Constants.RegionSize)),
693 (uint)(int)position.X,
694 (uint)(int)position.Y,
695 (uint)(int)position.Z);
696 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero,
697 "Region", agent.UUID,
698 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
699 "", gotoLocation, false, new Vector3(127, 0, 0),
700 new Byte[0]);
701 im.SendInstantMessage(m, delegate(bool success)
702 {
703 m_log.DebugFormat("[AGENT TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
704 });
705
706 }
707 }
708
709 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
710 {
711 InformClientToInitateTeleportToLocationDelegate icon =
712 (InformClientToInitateTeleportToLocationDelegate)iar.AsyncState;
713 icon.EndInvoke(iar);
714 }
715
716 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying);
717
718 /// <summary>
719 /// This Closes child agents on neighboring regions
720 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
721 /// </summary>
722 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying)
723 {
724 m_log.DebugFormat("[AGENT TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
725
726 Scene m_scene = agent.Scene;
727 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
728
729 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
730 GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
731
732 if (neighbourRegion != null && agent.ValidateAttachments())
733 {
734 pos = pos + (agent.Velocity);
735
736 SetInTransit(agent.UUID);
737 AgentData cAgent = new AgentData();
738 agent.CopyTo(cAgent);
739 cAgent.Position = pos;
740 if (isFlying)
741 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
742 cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort +
743 "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/";
744
745 m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent);
746
747 // Next, let's close the child agent connections that are too far away.
748 agent.CloseChildAgents(neighbourx, neighboury);
749
750 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
751 agent.ControllingClient.RequestClientInfo();
752
753 //m_log.Debug("BEFORE CROSS");
754 //Scene.DumpChildrenSeeds(UUID);
755 //DumpKnownRegions();
756 string agentcaps;
757 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
758 {
759 m_log.ErrorFormat("[AGENT TRANSFER MODULE]: No AGENT TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
760 neighbourRegion.RegionHandle);
761 return agent;
762 }
763 // TODO Should construct this behind a method
764 string capsPath =
765 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
766 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
767
768 m_log.DebugFormat("[AGENT TRANSFER MODULE]: Sending new AGENT TRANSFER MODULE seed url {0} to client {1}", capsPath, agent.UUID);
769
770 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
771 if (eq != null)
772 {
773 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
774 capsPath, agent.UUID, agent.ControllingClient.SessionId);
775 }
776 else
777 {
778 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
779 capsPath);
780 }
781
782 if (!WaitForCallback(agent.UUID))
783 {
784 m_log.Debug("[AGENT TRANSFER MODULE]: Callback never came in crossing agent");
785 ResetFromTransit(agent.UUID);
786
787 // Yikes! We should just have a ref to scene here.
788 //agent.Scene.InformClientOfNeighbours(agent);
789 EnableChildAgents(agent);
790
791 return agent;
792 }
793
794 agent.MakeChildAgent();
795 // now we have a child agent in this region. Request all interesting data about other (root) agents
796 agent.SendInitialFullUpdateToAllClients();
797
798 agent.CrossAttachmentsIntoNewRegion(neighbourRegion, true);
799
800 // m_scene.SendKillObject(m_localId);
801
802 agent.Scene.NotifyMyCoarseLocationChange();
803 // the user may change their profile information in other region,
804 // so the userinfo in UserProfileCache is not reliable any more, delete it
805 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
806 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
807 {
808 m_log.DebugFormat(
809 "[AGENT TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
810 }
811 }
812
813 //m_log.Debug("AFTER CROSS");
814 //Scene.DumpChildrenSeeds(UUID);
815 //DumpKnownRegions();
816 return agent;
817 }
818
819 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
820 {
821 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
822 ScenePresence agent = icon.EndInvoke(iar);
823
824 // If the cross was successful, this agent is a child agent
825 if (agent.IsChildAgent)
826 agent.Reset();
827 else // Not successful
828 agent.RestoreInCurrentScene();
829
830 // In any case
831 agent.NotInTransit();
832
833 //m_log.DebugFormat("[AGENT TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
834 }
835
836 #endregion
837
838
839 #region Enable Child Agents
840
841 private delegate void InformClientOfNeighbourDelegate(
842 ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent);
843
844 /// <summary>
845 /// This informs all neighboring regions about agent "avatar".
846 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
847 /// </summary>
848 public void EnableChildAgents(ScenePresence sp)
849 {
850 List<GridRegion> neighbours = new List<GridRegion>();
851 RegionInfo m_regionInfo = sp.Scene.RegionInfo;
852
853 if (m_regionInfo != null)
854 {
855 neighbours = RequestNeighbours(sp.Scene, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
856 }
857 else
858 {
859 m_log.Debug("[AGENT TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
860 }
861
862 /// We need to find the difference between the new regions where there are no child agents
863 /// and the regions where there are already child agents. We only send notification to the former.
864 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
865 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
866 List<ulong> previousRegionNeighbourHandles;
867
868 if (sp.Scene.CapsModule != null)
869 {
870 previousRegionNeighbourHandles =
871 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys);
872 }
873 else
874 {
875 previousRegionNeighbourHandles = new List<ulong>();
876 }
877
878 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
879 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
880
881 //Dump("Current Neighbors", neighbourHandles);
882 //Dump("Previous Neighbours", previousRegionNeighbourHandles);
883 //Dump("New Neighbours", newRegions);
884 //Dump("Old Neighbours", oldRegions);
885
886 /// Update the scene presence's known regions here on this region
887 sp.DropOldNeighbours(oldRegions);
888
889 /// Collect as many seeds as possible
890 Dictionary<ulong, string> seeds;
891 if (sp.Scene.CapsModule != null)
892 seeds
893 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
894 else
895 seeds = new Dictionary<ulong, string>();
896
897 //m_log.Debug(" !!! No. of seeds: " + seeds.Count);
898 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
899 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
900
901 /// Create the necessary child agents
902 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
903 foreach (GridRegion neighbour in neighbours)
904 {
905 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
906 {
907
908 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
909 agent.BaseFolder = UUID.Zero;
910 agent.InventoryFolder = UUID.Zero;
911 agent.startpos = new Vector3(128, 128, 70);
912 agent.child = true;
913 agent.Appearance = sp.Appearance;
914
915 if (newRegions.Contains(neighbour.RegionHandle))
916 {
917 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
918 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
919 seeds.Add(neighbour.RegionHandle, agent.CapsPath);
920 }
921 else
922 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle);
923
924 cagents.Add(agent);
925 }
926 }
927
928 /// Update all child agent with everyone's seeds
929 foreach (AgentCircuitData a in cagents)
930 {
931 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
932 }
933
934 if (sp.Scene.CapsModule != null)
935 {
936 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
937 }
938 sp.KnownRegions = seeds;
939 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
940 //avatar.DumpKnownRegions();
941
942 bool newAgent = false;
943 int count = 0;
944 foreach (GridRegion neighbour in neighbours)
945 {
946 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName);
947 // Don't do it if there's already an agent in that region
948 if (newRegions.Contains(neighbour.RegionHandle))
949 newAgent = true;
950 else
951 newAgent = false;
952
953 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
954 {
955 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
956 try
957 {
958 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
959 InformClientOfNeighbourCompleted,
960 d);
961 }
962
963 catch (ArgumentOutOfRangeException)
964 {
965 m_log.ErrorFormat(
966 "[AGENT TRANSFER MODULE]: 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}).",
967 neighbour.ExternalHostName,
968 neighbour.RegionHandle,
969 neighbour.RegionLocX,
970 neighbour.RegionLocY);
971 }
972 catch (Exception e)
973 {
974 m_log.ErrorFormat(
975 "[AGENT TRANSFER MODULE]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
976 neighbour.ExternalHostName,
977 neighbour.RegionHandle,
978 neighbour.RegionLocX,
979 neighbour.RegionLocY,
980 e);
981
982 // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
983 // since I don't know what will happen if we just let the client continue
984
985 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
986 // throw e;
987
988 }
989 }
990 count++;
991 }
992 }
993
994 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
995 {
996 InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate)iar.AsyncState;
997 icon.EndInvoke(iar);
998 //m_log.WarnFormat(" --> InformClientOfNeighbourCompleted");
999 }
1000
1001 /// <summary>
1002 /// Async component for informing client of which neighbours exist
1003 /// </summary>
1004 /// <remarks>
1005 /// This needs to run asynchronously, as a network timeout may block the thread for a long while
1006 /// </remarks>
1007 /// <param name="remoteClient"></param>
1008 /// <param name="a"></param>
1009 /// <param name="regionHandle"></param>
1010 /// <param name="endPoint"></param>
1011 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg,
1012 IPEndPoint endPoint, bool newAgent)
1013 {
1014 // Let's wait just a little to give time to originating regions to catch up with closing child agents
1015 // after a cross here
1016 Thread.Sleep(500);
1017
1018 Scene m_scene = sp.Scene;
1019
1020 uint x, y;
1021 Utils.LongToUInts(reg.RegionHandle, out x, out y);
1022 x = x / Constants.RegionSize;
1023 y = y / Constants.RegionSize;
1024 m_log.Info("[AGENT TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
1025
1026 string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
1027 + "/CAPS/" + a.CapsPath + "0000/";
1028
1029 string reason = String.Empty;
1030
1031
1032 bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, 0, out reason); // m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, 0, out reason);
1033
1034 if (regionAccepted && newAgent)
1035 {
1036 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
1037 if (eq != null)
1038 {
1039 #region IP Translation for NAT
1040 IClientIPEndpoint ipepClient;
1041 if (sp.ClientView.TryGet(out ipepClient))
1042 {
1043 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1044 }
1045 #endregion
1046
1047 eq.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID);
1048 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
1049 m_log.DebugFormat("[AGENT TRANSFER MODULE]: Sending new AGENT TRANSFER MODULE seed url {0} to client {1} in region {2}",
1050 capsPath, sp.UUID, sp.Scene.RegionInfo.RegionName);
1051 }
1052 else
1053 {
1054 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
1055 // TODO: make Event Queue disablable!
1056 }
1057
1058 m_log.Info("[AGENT TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString());
1059
1060 }
1061
1062 }
1063
1064 protected List<GridRegion> RequestNeighbours(Scene pScene, uint pRegionLocX, uint pRegionLocY)
1065 {
1066 RegionInfo m_regionInfo = pScene.RegionInfo;
1067
1068 Border[] northBorders = pScene.NorthBorders.ToArray();
1069 Border[] southBorders = pScene.SouthBorders.ToArray();
1070 Border[] eastBorders = pScene.EastBorders.ToArray();
1071 Border[] westBorders = pScene.WestBorders.ToArray();
1072
1073 // Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement.
1074 if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1)
1075 {
1076 return pScene.GridService.GetNeighbours(m_regionInfo.ScopeID, m_regionInfo.RegionID);
1077 }
1078 else
1079 {
1080 Vector2 extent = Vector2.Zero;
1081 for (int i = 0; i < eastBorders.Length; i++)
1082 {
1083 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1084 }
1085 for (int i = 0; i < northBorders.Length; i++)
1086 {
1087 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1088 }
1089
1090 // Loss of fraction on purpose
1091 extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
1092 extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
1093
1094 int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize;
1095 int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize;
1096
1097 int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize;
1098 int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize;
1099
1100 List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
1101 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
1102
1103 return neighbours;
1104 }
1105 }
1106
1107 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1108 {
1109 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
1110 }
1111
1112 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1113 // {
1114 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
1115 // }
1116
1117 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1118 {
1119 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
1120 }
1121
1122 private List<ulong> NeighbourHandles(List<GridRegion> neighbours)
1123 {
1124 List<ulong> handles = new List<ulong>();
1125 foreach (GridRegion reg in neighbours)
1126 {
1127 handles.Add(reg.RegionHandle);
1128 }
1129 return handles;
1130 }
1131
1132 private void Dump(string msg, List<ulong> handles)
1133 {
1134 m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
1135 foreach (ulong handle in handles)
1136 {
1137 uint x, y;
1138 Utils.LongToUInts(handle, out x, out y);
1139 x = x / Constants.RegionSize;
1140 y = y / Constants.RegionSize;
1141 m_log.InfoFormat("({0}, {1})", x, y);
1142 }
1143 }
1144
1145 #endregion
1146
1147
1148 #region Agent Arrived
1149 public void AgentArrivedAtDestination(UUID id)
1150 {
1151 //m_log.Debug(" >>> ReleaseAgent called <<< ");
1152 ResetFromTransit(id);
1153 }
1154
1155 #endregion
1156
1157
1158 #region Misc
1159
1160 protected bool WaitForCallback(UUID id)
1161 {
1162 int count = 200;
1163 while (m_agentsInTransit.Contains(id) && count-- > 0)
1164 {
1165 //m_log.Debug(" >>> Waiting... " + count);
1166 Thread.Sleep(100);
1167 }
1168
1169 if (count > 0)
1170 return true;
1171 else
1172 return false;
1173 }
1174
1175 protected void SetInTransit(UUID id)
1176 {
1177 lock (m_agentsInTransit)
1178 {
1179 if (!m_agentsInTransit.Contains(id))
1180 m_agentsInTransit.Add(id);
1181 }
1182 }
1183
1184 protected bool ResetFromTransit(UUID id)
1185 {
1186 lock (m_agentsInTransit)
1187 {
1188 if (m_agentsInTransit.Contains(id))
1189 {
1190 m_agentsInTransit.Remove(id);
1191 return true;
1192 }
1193 }
1194 return false;
1195 }
1196
1197
1198 #endregion
1199
1200 }
1201}