aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/Scene.cs')
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs806
1 files changed, 806 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
new file mode 100644
index 0000000..d1f6038
--- /dev/null
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -0,0 +1,806 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.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*/
28using System;
29using System.Collections.Generic;
30using System.Threading;
31using System.Timers;
32using libsecondlife;
33using libsecondlife.Packets;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Framework.Console;
37using OpenSim.Framework.Interfaces;
38using OpenSim.Framework.Servers;
39using OpenSim.Framework.Types;
40using OpenSim.Physics.Manager;
41using OpenSim.Region.Caches;
42using OpenSim.Region.Environment.Scripting;
43using OpenSim.Region.Terrain;
44using Caps=OpenSim.Region.Capabilities.Caps;
45using Timer=System.Timers.Timer;
46
47namespace OpenSim.Region.Environment.Scenes
48{
49 public delegate bool FilterAvatarList(ScenePresence avatar);
50
51 public partial class Scene : SceneBase, ILocalStorageReceiver
52 {
53 protected Timer m_heartbeatTimer = new Timer();
54 protected Dictionary<LLUUID, ScenePresence> Avatars;
55 protected Dictionary<LLUUID, SceneObject> Prims;
56 private PhysicsScene phyScene;
57 private float timeStep = 0.1f;
58 private Random Rand = new Random();
59 private uint _primCount = 702000;
60 private System.Threading.Mutex _primAllocateMutex = new Mutex(false);
61 private int storageCount;
62 private Mutex updateLock;
63
64 protected AuthenticateSessionsBase authenticateHandler;
65 protected RegionCommsListener regionCommsHost;
66 protected CommunicationsManager commsManager;
67
68 protected Dictionary<LLUUID, Caps> capsHandlers = new Dictionary<LLUUID, Caps>();
69 protected BaseHttpServer httpListener;
70
71 public ParcelManager parcelManager;
72 public EstateManager estateManager;
73 public EventManager eventManager;
74 public ScriptManager scriptManager;
75
76 #region Properties
77 /// <summary>
78 ///
79 /// </summary>
80 public PhysicsScene PhysScene
81 {
82 set
83 {
84 this.phyScene = value;
85 }
86 get
87 {
88 return (this.phyScene);
89 }
90 }
91
92 #endregion
93
94 #region Constructors
95 /// <summary>
96 /// Creates a new World class, and a region to go with it.
97 /// </summary>
98 /// <param name="clientThreads">Dictionary to contain client threads</param>
99 /// <param name="regionHandle">Region Handle for this region</param>
100 /// <param name="regionName">Region Name for this region</param>
101 public Scene(ClientManager clientManager, RegionInfo regInfo, AuthenticateSessionsBase authen, CommunicationsManager commsMan, AssetCache assetCach, BaseHttpServer httpServer)
102 {
103 updateLock = new Mutex(false);
104 this.authenticateHandler = authen;
105 this.commsManager = commsMan;
106 this.assetCache = assetCach;
107 m_clientManager = clientManager;
108 m_regInfo = regInfo;
109 m_regionHandle = m_regInfo.RegionHandle;
110 m_regionName = m_regInfo.RegionName;
111 this.m_datastore = m_regInfo.DataStore;
112 this.RegisterRegionWithComms();
113
114 parcelManager = new ParcelManager(this, this.m_regInfo);
115 estateManager = new EstateManager(this, this.m_regInfo);
116 scriptManager = new ScriptManager(this);
117 eventManager = new EventManager();
118
119 MainLog.Instance.Verbose("World.cs - creating new entitities instance");
120 Entities = new Dictionary<LLUUID, EntityBase>();
121 Avatars = new Dictionary<LLUUID, ScenePresence>();
122 Prims = new Dictionary<LLUUID, SceneObject>();
123
124 MainLog.Instance.Verbose("World.cs - creating LandMap");
125 Terrain = new TerrainEngine();
126
127 ScenePresence.LoadAnims();
128 this.httpListener = httpServer;
129 }
130 #endregion
131
132 /// <summary>
133 ///
134 /// </summary>
135 public void StartTimer()
136 {
137 m_heartbeatTimer.Enabled = true;
138 m_heartbeatTimer.Interval = 100;
139 m_heartbeatTimer.Elapsed += new ElapsedEventHandler(this.Heartbeat);
140 }
141
142
143 #region Update Methods
144
145
146 /// <summary>
147 /// Performs per-frame updates regularly
148 /// </summary>
149 /// <param name="sender"></param>
150 /// <param name="e"></param>
151 void Heartbeat(object sender, EventArgs e)
152 {
153 this.Update();
154 }
155
156 /// <summary>
157 /// Performs per-frame updates on the world, this should be the central world loop
158 /// </summary>
159 public override void Update()
160 {
161 updateLock.WaitOne();
162 try
163 {
164 if (this.phyScene.IsThreaded)
165 {
166 this.phyScene.GetResults();
167
168 }
169
170 foreach (LLUUID UUID in Entities.Keys)
171 {
172 Entities[UUID].updateMovement();
173 }
174
175 lock (this.m_syncRoot)
176 {
177 this.phyScene.Simulate(timeStep);
178 }
179
180 foreach (LLUUID UUID in Entities.Keys)
181 {
182 Entities[UUID].update();
183 }
184
185 // General purpose event manager
186 eventManager.TriggerOnFrame();
187
188 //backup world data
189 this.storageCount++;
190 if (storageCount > 1200) //set to how often you want to backup
191 {
192 this.Backup();
193 storageCount = 0;
194 }
195 }
196 catch (Exception e)
197 {
198 MainLog.Instance.Warn("World.cs: Update() - Failed with exception " + e.ToString());
199 }
200 updateLock.ReleaseMutex();
201
202 }
203
204 /// <summary>
205 ///
206 /// </summary>
207 /// <returns></returns>
208 public bool Backup()
209 {
210
211 return true;
212 }
213 #endregion
214
215 #region Regenerate Terrain
216
217 /// <summary>
218 /// Rebuilds the terrain using a procedural algorithm
219 /// </summary>
220 public void RegenerateTerrain()
221 {
222 try
223 {
224 Terrain.hills();
225
226 lock (this.m_syncRoot)
227 {
228 this.phyScene.SetTerrain(Terrain.getHeights1D());
229 }
230 this.localStorage.SaveMap(this.Terrain.getHeights1D());
231
232 m_clientManager.ForEachClient(delegate(IClientAPI client)
233 {
234 this.SendLayerData(client);
235 });
236
237 foreach (LLUUID UUID in Entities.Keys)
238 {
239 Entities[UUID].LandRenegerated();
240 }
241 }
242 catch (Exception e)
243 {
244 MainLog.Instance.Warn("World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
245 }
246 }
247
248 /// <summary>
249 /// Rebuilds the terrain using a 2D float array
250 /// </summary>
251 /// <param name="newMap">256,256 float array containing heights</param>
252 public void RegenerateTerrain(float[,] newMap)
253 {
254 try
255 {
256 this.Terrain.setHeights2D(newMap);
257 lock (this.m_syncRoot)
258 {
259 this.phyScene.SetTerrain(this.Terrain.getHeights1D());
260 }
261 this.localStorage.SaveMap(this.Terrain.getHeights1D());
262
263 m_clientManager.ForEachClient(delegate(IClientAPI client)
264 {
265 this.SendLayerData(client);
266 });
267
268 foreach (LLUUID UUID in Entities.Keys)
269 {
270 Entities[UUID].LandRenegerated();
271 }
272 }
273 catch (Exception e)
274 {
275 MainLog.Instance.Warn("World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
276 }
277 }
278
279 /// <summary>
280 /// Rebuilds the terrain assuming changes occured at a specified point[?]
281 /// </summary>
282 /// <param name="changes">???</param>
283 /// <param name="pointx">???</param>
284 /// <param name="pointy">???</param>
285 public void RegenerateTerrain(bool changes, int pointx, int pointy)
286 {
287 try
288 {
289 if (changes)
290 {
291 /* Dont save here, rely on tainting system instead */
292
293 m_clientManager.ForEachClient(delegate(IClientAPI client)
294 {
295 this.SendLayerData(pointx, pointy, client);
296 });
297 }
298 }
299 catch (Exception e)
300 {
301 MainLog.Instance.Warn("World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
302 }
303 }
304
305 #endregion
306
307 #region Load Terrain
308 /// <summary>
309 /// Loads the World heightmap
310 /// </summary>
311 ///
312 public override void LoadWorldMap()
313 {
314 try
315 {
316 float[] map = this.localStorage.LoadWorld();
317 if (map == null)
318 {
319 if (string.IsNullOrEmpty(this.m_regInfo.estateSettings.terrainFile))
320 {
321 Console.WriteLine("No default terrain, procedurally generating...");
322 this.Terrain.hills();
323
324 this.localStorage.SaveMap(this.Terrain.getHeights1D());
325 }
326 else
327 {
328 try
329 {
330 this.Terrain.loadFromFileF32(this.m_regInfo.estateSettings.terrainFile);
331 this.Terrain *= this.m_regInfo.estateSettings.terrainMultiplier;
332 }
333 catch
334 {
335 Console.WriteLine("Unable to load default terrain, procedurally generating instead...");
336 Terrain.hills();
337 }
338 this.localStorage.SaveMap(this.Terrain.getHeights1D());
339 }
340 }
341 else
342 {
343 this.Terrain.setHeights1D(map);
344 }
345
346 CreateTerrainTexture();
347
348 }
349 catch (Exception e)
350 {
351 MainLog.Instance.Warn("World.cs: LoadWorldMap() - Failed with exception " + e.ToString());
352 }
353 }
354
355 /// <summary>
356 ///
357 /// </summary>
358 private void CreateTerrainTexture()
359 {
360 //create a texture asset of the terrain
361 byte[] data = this.Terrain.exportJpegImage("defaultstripe.png");
362 this.m_regInfo.estateSettings.terrainImageID = LLUUID.Random();
363 AssetBase asset = new AssetBase();
364 asset.FullID = this.m_regInfo.estateSettings.terrainImageID;
365 asset.Data = data;
366 asset.Name = "terrainImage";
367 asset.Type = 0;
368 this.assetCache.AddAsset(asset);
369 }
370 #endregion
371
372 #region Primitives Methods
373
374
375 /// <summary>
376 /// Loads the World's objects
377 /// </summary>
378 public void LoadPrimsFromStorage()
379 {
380 try
381 {
382 MainLog.Instance.Verbose("World.cs: LoadPrimsFromStorage() - Loading primitives");
383 this.localStorage.LoadPrimitives(this);
384 }
385 catch (Exception e)
386 {
387 MainLog.Instance.Warn("World.cs: LoadPrimsFromStorage() - Failed with exception " + e.ToString());
388 }
389 }
390
391 /// <summary>
392 /// Loads a specific object from storage
393 /// </summary>
394 /// <param name="prim">The object to load</param>
395 public void PrimFromStorage(PrimData prim)
396 {
397
398 }
399
400 /// <summary>
401 /// Returns a new unallocated primitive ID
402 /// </summary>
403 /// <returns>A brand new primitive ID</returns>
404 public uint PrimIDAllocate()
405 {
406 uint myID;
407
408 _primAllocateMutex.WaitOne();
409 ++_primCount;
410 myID = _primCount;
411 _primAllocateMutex.ReleaseMutex();
412
413 return myID;
414 }
415
416 /// <summary>
417 ///
418 /// </summary>
419 /// <param name="addPacket"></param>
420 /// <param name="agentClient"></param>
421 public void AddNewPrim(Packet addPacket, IClientAPI agentClient)
422 {
423 AddNewPrim((ObjectAddPacket)addPacket, agentClient.AgentId);
424 }
425
426 /// <summary>
427 ///
428 /// </summary>
429 /// <param name="addPacket"></param>
430 /// <param name="ownerID"></param>
431 public void AddNewPrim(ObjectAddPacket addPacket, LLUUID ownerID)
432 {
433 try
434 {
435 SceneObject sceneOb = new SceneObject(m_regionHandle, this, addPacket, ownerID, this.PrimIDAllocate());
436 this.Entities.Add(sceneOb.rootUUID, sceneOb);
437
438 // Trigger event for listeners
439 // eventManager.TriggerOnNewPrimitive(prim);
440 }
441 catch (Exception e)
442 {
443 MainLog.Instance.Warn("World.cs: AddNewPrim() - Failed with exception " + e.ToString());
444 }
445 }
446
447 public override uint AddNewPrim(LLUUID ownerId, PrimData primData, LLVector3 pos, LLQuaternion rotation, LLUUID texture, int flags)
448 {
449 uint id = NextLocalId;
450
451 throw new NotImplementedException("Not implemented yet.");
452 }
453
454 #endregion
455
456 #region Add/Remove Avatar Methods
457
458 /// <summary>
459 ///
460 /// </summary>
461 /// <param name="remoteClient"></param
462 /// <param name="agentID"></param>
463 /// <param name="child"></param>
464 public override void AddNewClient(IClientAPI client, bool child)
465 {
466 client.OnRegionHandShakeReply += this.SendLayerData;
467 //remoteClient.OnRequestWearables += new GenericCall(this.GetInitialPrims);
468 client.OnChatFromViewer += this.SimChat;
469 client.OnInstantMessage += this.InstantMessage;
470 client.OnRequestWearables += this.InformClientOfNeighbours;
471 client.OnAddPrim += this.AddNewPrim;
472 client.OnUpdatePrimGroupPosition += this.UpdatePrimPosition;
473 client.OnUpdatePrimSinglePosition += this.UpdatePrimSinglePosition;
474 client.OnUpdatePrimGroupRotation += this.UpdatePrimRotation;
475 client.OnUpdatePrimGroupMouseRotation += this.UpdatePrimRotation;
476 client.OnUpdatePrimSingleRotation += this.UpdatePrimSingleRotation;
477 client.OnUpdatePrimScale += this.UpdatePrimScale;
478 client.OnUpdatePrimShape += this.UpdatePrimShape;
479 client.OnRequestMapBlocks += this.RequestMapBlocks;
480 client.OnTeleportLocationRequest += this.RequestTeleportLocation;
481 client.OnObjectSelect += this.SelectPrim;
482 client.OnGrapUpdate += this.MoveObject;
483 client.OnNameFromUUIDRequest += this.commsManager.HandleUUIDNameRequest;
484 client.OnObjectDescription += this.PrimDescription;
485 client.OnObjectName += this.PrimName;
486 client.OnLinkObjects += this.LinkObjects;
487 client.OnObjectDuplicate += this.DuplicateObject;
488
489 /* remoteClient.OnParcelPropertiesRequest += new ParcelPropertiesRequest(parcelManager.handleParcelPropertiesRequest);
490 remoteClient.OnParcelDivideRequest += new ParcelDivideRequest(parcelManager.handleParcelDivideRequest);
491 remoteClient.OnParcelJoinRequest += new ParcelJoinRequest(parcelManager.handleParcelJoinRequest);
492 remoteClient.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(parcelManager.handleParcelPropertiesUpdateRequest);
493 remoteClient.OnEstateOwnerMessage += new EstateOwnerMessageRequest(estateManager.handleEstateOwnerMessage);
494 */
495 this.estateManager.sendRegionHandshake(client);
496
497 CreateAndAddScenePresence(client);
498 return;
499 }
500
501 protected void CreateAndAddScenePresence(IClientAPI client)
502 {
503 ScenePresence newAvatar = null;
504
505 MainLog.Instance.Verbose("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent");
506 newAvatar = new ScenePresence(client, this, this.m_regInfo);
507 MainLog.Instance.Verbose("World.cs:AddViewerAgent() - Adding new avatar to world");
508 MainLog.Instance.Verbose("World.cs:AddViewerAgent() - Starting RegionHandshake ");
509
510 PhysicsVector pVec = new PhysicsVector(newAvatar.Pos.X, newAvatar.Pos.Y, newAvatar.Pos.Z);
511 lock (this.m_syncRoot)
512 {
513 newAvatar.PhysActor = this.phyScene.AddAvatar(pVec);
514 }
515
516 lock (Entities)
517 {
518 if (!Entities.ContainsKey(client.AgentId))
519 {
520 this.Entities.Add(client.AgentId, newAvatar);
521 }
522 else
523 {
524 Entities[client.AgentId] = newAvatar;
525 }
526 }
527 lock (Avatars)
528 {
529 if (Avatars.ContainsKey(client.AgentId))
530 {
531 Avatars[client.AgentId] = newAvatar;
532 }
533 else
534 {
535 this.Avatars.Add(client.AgentId, newAvatar);
536 }
537 }
538 }
539
540
541 /// <summary>
542 ///
543 /// </summary>
544 /// <param name="agentID"></param>
545 public override void RemoveClient(LLUUID agentID)
546 {
547 eventManager.TriggerOnRemovePresence(agentID);
548
549 ScenePresence avatar = this.RequestAvatar(agentID);
550
551 m_clientManager.ForEachClient(
552 delegate(IClientAPI client)
553 {
554 client.SendKillObject(avatar.RegionHandle, avatar.LocalId);
555 });
556
557 lock (Avatars) {
558 if (Avatars.ContainsKey(agentID)) {
559 Avatars.Remove(agentID);
560 }
561 }
562 lock (Entities) {
563 if (Entities.ContainsKey(agentID)) {
564 Entities.Remove(agentID);
565 }
566 }
567 // TODO: Add the removal from physics ?
568
569
570
571 return;
572 }
573 #endregion
574
575 #region Request Avatars List Methods
576 //The idea is to have a group of method that return a list of avatars meeting some requirement
577 // ie it could be all Avatars within a certain range of the calling prim/avatar.
578
579 /// <summary>
580 /// Request a List of all Avatars in this World
581 /// </summary>
582 /// <returns></returns>
583 public List<ScenePresence> RequestAvatarList()
584 {
585 List<ScenePresence> result = new List<ScenePresence>();
586
587 foreach (ScenePresence avatar in Avatars.Values)
588 {
589 result.Add(avatar);
590 }
591
592 return result;
593 }
594
595 /// <summary>
596 /// Request a filtered list of Avatars in this World
597 /// </summary>
598 /// <returns></returns>
599 public List<ScenePresence> RequestAvatarList(FilterAvatarList filter)
600 {
601 List<ScenePresence> result = new List<ScenePresence>();
602
603 foreach (ScenePresence avatar in Avatars.Values)
604 {
605 if (filter(avatar))
606 {
607 result.Add(avatar);
608 }
609 }
610
611 return result;
612 }
613
614 /// <summary>
615 /// Request a Avatar by UUID
616 /// </summary>
617 /// <param name="avatarID"></param>
618 /// <returns></returns>
619 public ScenePresence RequestAvatar(LLUUID avatarID)
620 {
621 if (this.Avatars.ContainsKey(avatarID))
622 {
623 return Avatars[avatarID];
624 }
625 return null;
626 }
627 #endregion
628
629
630 /// <summary>
631 ///
632 /// </summary>
633 /// <param name="entID"></param>
634 /// <returns></returns>
635 public bool DeleteEntity(LLUUID entID)
636 {
637 if (this.Entities.ContainsKey(entID))
638 {
639 this.Entities.Remove(entID);
640 return true;
641 }
642 return false;
643 }
644
645 public void SendAllSceneObjectsToClient(IClientAPI client)
646 {
647 foreach (EntityBase ent in Entities.Values)
648 {
649 if (ent is SceneObject)
650 {
651 ((SceneObject)ent).SendAllChildPrimsToClient(client);
652 }
653 }
654 }
655
656 #region RegionCommsHost
657
658 /// <summary>
659 ///
660 /// </summary>
661 public void RegisterRegionWithComms()
662 {
663
664 this.regionCommsHost = this.commsManager.GridServer.RegisterRegion(this.m_regInfo);
665 if (this.regionCommsHost != null)
666 {
667 this.regionCommsHost.OnExpectUser += this.NewUserConnection;
668 this.regionCommsHost.OnAvatarCrossingIntoRegion += this.AgentCrossing;
669 }
670 }
671
672 /// <summary>
673 ///
674 /// </summary>
675 /// <param name="regionHandle"></param>
676 /// <param name="agent"></param>
677 public void NewUserConnection(ulong regionHandle, AgentCircuitData agent)
678 {
679 // Console.WriteLine("World.cs - add new user connection");
680 //should just check that its meant for this region
681 if (regionHandle == this.m_regInfo.RegionHandle)
682 {
683 if (agent.CapsPath != "")
684 {
685 //Console.WriteLine("new user, so creating caps handler for it");
686 Caps cap = new Caps(this.assetCache, httpListener, this.m_regInfo.ExternalHostName, this.m_regInfo.ExternalEndPoint.Port, agent.CapsPath, agent.AgentID);
687 cap.RegisterHandlers();
688 this.capsHandlers.Add(agent.AgentID, cap);
689 }
690 this.authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
691 }
692 }
693
694 public void AgentCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position)
695 {
696 if (regionHandle == this.m_regInfo.RegionHandle)
697 {
698 if (this.Avatars.ContainsKey(agentID))
699 {
700 this.Avatars[agentID].MakeAvatar(position);
701 }
702 }
703 }
704
705 /// <summary>
706 ///
707 /// </summary>
708 public void InformClientOfNeighbours(IClientAPI remoteClient)
709 {
710 List<RegionInfo> neighbours = this.commsManager.GridServer.RequestNeighbours(this.m_regInfo);
711
712 if (neighbours != null)
713 {
714 for (int i = 0; i < neighbours.Count; i++)
715 {
716 AgentCircuitData agent = remoteClient.RequestClientInfo();
717 agent.BaseFolder = LLUUID.Zero;
718 agent.InventoryFolder = LLUUID.Zero;
719 agent.startpos = new LLVector3(128, 128, 70);
720 agent.child = true;
721 this.commsManager.InterRegion.InformRegionOfChildAgent(neighbours[i].RegionHandle, agent);
722 remoteClient.InformClientOfNeighbour(neighbours[i].RegionHandle, neighbours[i].ExternalEndPoint);
723 //this.capsHandlers[remoteClient.AgentId].CreateEstablishAgentComms("", System.Net.IPAddress.Parse(neighbours[i].CommsIPListenAddr) + ":" + neighbours[i].CommsIPListenPort);
724 }
725 }
726 }
727
728 /// <summary>
729 ///
730 /// </summary>
731 /// <param name="regionHandle"></param>
732 /// <returns></returns>
733 public RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
734 {
735 return this.commsManager.GridServer.RequestNeighbourInfo(regionHandle);
736 }
737
738 /// <summary>
739 ///
740 /// </summary>
741 /// <param name="minX"></param>
742 /// <param name="minY"></param>
743 /// <param name="maxX"></param>
744 /// <param name="maxY"></param>
745 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
746 {
747 List<MapBlockData> mapBlocks;
748 mapBlocks = this.commsManager.GridServer.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
749 remoteClient.SendMapBlock(mapBlocks);
750 }
751
752 /// <summary>
753 ///
754 /// </summary>
755 /// <param name="remoteClient"></param>
756 /// <param name="RegionHandle"></param>
757 /// <param name="position"></param>
758 /// <param name="lookAt"></param>
759 /// <param name="flags"></param>
760 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, LLVector3 position, LLVector3 lookAt, uint flags)
761 {
762 if (regionHandle == this.m_regionHandle)
763 {
764 if (this.Avatars.ContainsKey(remoteClient.AgentId))
765 {
766 remoteClient.SendTeleportLocationStart();
767 remoteClient.SendLocalTeleport(position, lookAt, flags);
768 this.Avatars[remoteClient.AgentId].Teleport(position);
769 }
770 }
771 else
772 {
773 RegionInfo reg = this.RequestNeighbouringRegionInfo(regionHandle);
774 if (reg != null)
775 {
776 remoteClient.SendTeleportLocationStart();
777 AgentCircuitData agent = remoteClient.RequestClientInfo();
778 agent.BaseFolder = LLUUID.Zero;
779 agent.InventoryFolder = LLUUID.Zero;
780 agent.startpos = new LLVector3(128, 128, 70);
781 agent.child = true;
782 this.commsManager.InterRegion.InformRegionOfChildAgent(regionHandle, agent);
783 this.commsManager.InterRegion.ExpectAvatarCrossing(regionHandle, remoteClient.AgentId, position);
784
785 remoteClient.SendRegionTeleport(regionHandle, 13, reg.ExternalEndPoint, 4, (1 << 4));
786
787 }
788 //remoteClient.SendTeleportCancel();
789 }
790 }
791
792 /// <summary>
793 ///
794 /// </summary>
795 /// <param name="regionhandle"></param>
796 /// <param name="agentID"></param>
797 /// <param name="position"></param>
798 public bool InformNeighbourOfCrossing(ulong regionhandle, LLUUID agentID, LLVector3 position)
799 {
800 return this.commsManager.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position);
801 }
802
803 #endregion
804
805 }
806}