corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
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 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Text;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Threading;
32 using OpenMetaverse.StructuredData;
33 using OpenMetaverse.Http;
34 using OpenMetaverse.Packets;
35  
36 namespace OpenMetaverse
37 {
38 #region Enums
39  
40 /// <summary>
41 /// Map layer request type
42 /// </summary>
43 public enum GridLayerType : uint
44 {
45 /// <summary>Objects and terrain are shown</summary>
46 Objects = 0,
47 /// <summary>Only the terrain is shown, no objects</summary>
48 Terrain = 1,
49 /// <summary>Overlay showing land for sale and for auction</summary>
50 LandForSale = 2
51 }
52  
53 /// <summary>
54 /// Type of grid item, such as telehub, event, populator location, etc.
55 /// </summary>
56 public enum GridItemType : uint
57 {
58 /// <summary>Telehub</summary>
59 Telehub = 1,
60 /// <summary>PG rated event</summary>
61 PgEvent = 2,
62 /// <summary>Mature rated event</summary>
63 MatureEvent = 3,
64 /// <summary>Popular location</summary>
65 Popular = 4,
66 /// <summary>Locations of avatar groups in a region</summary>
67 AgentLocations = 6,
68 /// <summary>Land for sale</summary>
69 LandForSale = 7,
70 /// <summary>Classified ad</summary>
71 Classified = 8,
72 /// <summary>Adult rated event</summary>
73 AdultEvent = 9,
74 /// <summary>Adult land for sale</summary>
75 AdultLandForSale = 10
76 }
77  
78 #endregion Enums
79  
80 #region Structs
81  
82 /// <summary>
83 /// Information about a region on the grid map
84 /// </summary>
85 public struct GridRegion
86 {
87 /// <summary>Sim X position on World Map</summary>
88 public int X;
89 /// <summary>Sim Y position on World Map</summary>
90 public int Y;
91 /// <summary>Sim Name (NOTE: In lowercase!)</summary>
92 public string Name;
93 /// <summary></summary>
94 public SimAccess Access;
95 /// <summary>Appears to always be zero (None)</summary>
96 public RegionFlags RegionFlags;
97 /// <summary>Sim's defined Water Height</summary>
98 public byte WaterHeight;
99 /// <summary></summary>
100 public byte Agents;
101 /// <summary>UUID of the World Map image</summary>
102 public UUID MapImageID;
103 /// <summary>Unique identifier for this region, a combination of the X
104 /// and Y position</summary>
105 public ulong RegionHandle;
106  
107  
108 /// <summary>
109 ///
110 /// </summary>
111 /// <returns></returns>
112 public override string ToString()
113 {
114 return String.Format("{0} ({1}/{2}), Handle: {3}, MapImage: {4}, Access: {5}, Flags: {6}",
115 Name, X, Y, RegionHandle, MapImageID, Access, RegionFlags);
116 }
117  
118 /// <summary>
119 ///
120 /// </summary>
121 /// <returns></returns>
122 public override int GetHashCode()
123 {
124 return X.GetHashCode() ^ Y.GetHashCode();
125 }
126  
127 /// <summary>
128 ///
129 /// </summary>
130 /// <param name="obj"></param>
131 /// <returns></returns>
132 public override bool Equals(object obj)
133 {
134 if (obj is GridRegion)
135 return Equals((GridRegion)obj);
136 else
137 return false;
138 }
139  
140 private bool Equals(GridRegion region)
141 {
142 return (this.X == region.X && this.Y == region.Y);
143 }
144 }
145  
146 /// <summary>
147 /// Visual chunk of the grid map
148 /// </summary>
149 public struct GridLayer
150 {
151 public int Bottom;
152 public int Left;
153 public int Top;
154 public int Right;
155 public UUID ImageID;
156  
157 public bool ContainsRegion(int x, int y)
158 {
159 return (x >= Left && x <= Right && y >= Bottom && y <= Top);
160 }
161 }
162  
163 #endregion Structs
164  
165 #region Map Item Classes
166  
167 /// <summary>
168 /// Base class for Map Items
169 /// </summary>
170 public abstract class MapItem
171 {
172 /// <summary>The Global X position of the item</summary>
173 public uint GlobalX;
174 /// <summary>The Global Y position of the item</summary>
175 public uint GlobalY;
176  
177 /// <summary>Get the Local X position of the item</summary>
178 public uint LocalX { get { return GlobalX % 256; } }
179 /// <summary>Get the Local Y position of the item</summary>
180 public uint LocalY { get { return GlobalY % 256; } }
181  
182 /// <summary>Get the Handle of the region</summary>
183 public ulong RegionHandle
184 {
185 get { return Utils.UIntsToLong((uint)(GlobalX - (GlobalX % 256)), (uint)(GlobalY - (GlobalY % 256))); }
186 }
187 }
188  
189 /// <summary>
190 /// Represents an agent or group of agents location
191 /// </summary>
192 public class MapAgentLocation : MapItem
193 {
194 public int AvatarCount;
195 public string Identifier;
196 }
197  
198 /// <summary>
199 /// Represents a Telehub location
200 /// </summary>
201 public class MapTelehub : MapItem
202 {
203 }
204  
205 /// <summary>
206 /// Represents a non-adult parcel of land for sale
207 /// </summary>
208 public class MapLandForSale : MapItem
209 {
210 public int Size;
211 public int Price;
212 public string Name;
213 public UUID ID;
214 }
215  
216 /// <summary>
217 /// Represents an Adult parcel of land for sale
218 /// </summary>
219 public class MapAdultLandForSale : MapItem
220 {
221 public int Size;
222 public int Price;
223 public string Name;
224 public UUID ID;
225 }
226  
227 /// <summary>
228 /// Represents a PG Event
229 /// </summary>
230 public class MapPGEvent : MapItem
231 {
232 public DirectoryManager.EventFlags Flags; // Extra
233 public DirectoryManager.EventCategories Category; // Extra2
234 public string Description;
235 }
236  
237 /// <summary>
238 /// Represents a Mature event
239 /// </summary>
240 public class MapMatureEvent : MapItem
241 {
242 public DirectoryManager.EventFlags Flags; // Extra
243 public DirectoryManager.EventCategories Category; // Extra2
244 public string Description;
245 }
246  
247 /// <summary>
248 /// Represents an Adult event
249 /// </summary>
250 public class MapAdultEvent : MapItem
251 {
252 public DirectoryManager.EventFlags Flags; // Extra
253 public DirectoryManager.EventCategories Category; // Extra2
254 public string Description;
255 }
256 #endregion Grid Item Classes
257  
258 /// <summary>
259 /// Manages grid-wide tasks such as the world map
260 /// </summary>
261 public class GridManager
262 {
263 #region Delegates
264  
265 /// <summary>The event subscribers. null if no subcribers</summary>
266 private EventHandler<CoarseLocationUpdateEventArgs> m_CoarseLocationUpdate;
267  
268 /// <summary>Raises the CoarseLocationUpdate event</summary>
269 /// <param name="e">A CoarseLocationUpdateEventArgs object containing the
270 /// data sent by simulator</param>
271 protected virtual void OnCoarseLocationUpdate(CoarseLocationUpdateEventArgs e)
272 {
273 EventHandler<CoarseLocationUpdateEventArgs> handler = m_CoarseLocationUpdate;
274 if (handler != null)
275 handler(this, e);
276 }
277  
278 /// <summary>Thread sync lock object</summary>
279 private readonly object m_CoarseLocationUpdateLock = new object();
280  
281 /// <summary>Raised when the simulator sends a <see cref="CoarseLocationUpdatePacket"/>
282 /// containing the location of agents in the simulator</summary>
283 public event EventHandler<CoarseLocationUpdateEventArgs> CoarseLocationUpdate
284 {
285 add { lock (m_CoarseLocationUpdateLock) { m_CoarseLocationUpdate += value; } }
286 remove { lock (m_CoarseLocationUpdateLock) { m_CoarseLocationUpdate -= value; } }
287 }
288  
289 /// <summary>The event subscribers. null if no subcribers</summary>
290 private EventHandler<GridRegionEventArgs> m_GridRegion;
291  
292 /// <summary>Raises the GridRegion event</summary>
293 /// <param name="e">A GridRegionEventArgs object containing the
294 /// data sent by simulator</param>
295 protected virtual void OnGridRegion(GridRegionEventArgs e)
296 {
297 EventHandler<GridRegionEventArgs> handler = m_GridRegion;
298 if (handler != null)
299 handler(this, e);
300 }
301  
302 /// <summary>Thread sync lock object</summary>
303 private readonly object m_GridRegionLock = new object();
304  
305 /// <summary>Raised when the simulator sends a Region Data in response to
306 /// a Map request</summary>
307 public event EventHandler<GridRegionEventArgs> GridRegion
308 {
309 add { lock (m_GridRegionLock) { m_GridRegion += value; } }
310 remove { lock (m_GridRegionLock) { m_GridRegion -= value; } }
311 }
312  
313 /// <summary>The event subscribers. null if no subcribers</summary>
314 private EventHandler<GridLayerEventArgs> m_GridLayer;
315  
316 /// <summary>Raises the GridLayer event</summary>
317 /// <param name="e">A GridLayerEventArgs object containing the
318 /// data sent by simulator</param>
319 protected virtual void OnGridLayer(GridLayerEventArgs e)
320 {
321 EventHandler<GridLayerEventArgs> handler = m_GridLayer;
322 if (handler != null)
323 handler(this, e);
324 }
325  
326 /// <summary>Thread sync lock object</summary>
327 private readonly object m_GridLayerLock = new object();
328  
329 /// <summary>Raised when the simulator sends GridLayer object containing
330 /// a map tile coordinates and texture information</summary>
331 public event EventHandler<GridLayerEventArgs> GridLayer
332 {
333 add { lock (m_GridLayerLock) { m_GridLayer += value; } }
334 remove { lock (m_GridLayerLock) { m_GridLayer -= value; } }
335 }
336  
337 /// <summary>The event subscribers. null if no subcribers</summary>
338 private EventHandler<GridItemsEventArgs> m_GridItems;
339  
340 /// <summary>Raises the GridItems event</summary>
341 /// <param name="e">A GridItemEventArgs object containing the
342 /// data sent by simulator</param>
343 protected virtual void OnGridItems(GridItemsEventArgs e)
344 {
345 EventHandler<GridItemsEventArgs> handler = m_GridItems;
346 if (handler != null)
347 handler(this, e);
348 }
349  
350 /// <summary>Thread sync lock object</summary>
351 private readonly object m_GridItemsLock = new object();
352  
353 /// <summary>Raised when the simulator sends GridItems object containing
354 /// details on events, land sales at a specific location</summary>
355 public event EventHandler<GridItemsEventArgs> GridItems
356 {
357 add { lock (m_GridItemsLock) { m_GridItems += value; } }
358 remove { lock (m_GridItemsLock) { m_GridItems -= value; } }
359 }
360  
361 /// <summary>The event subscribers. null if no subcribers</summary>
362 private EventHandler<RegionHandleReplyEventArgs> m_RegionHandleReply;
363  
364 /// <summary>Raises the RegionHandleReply event</summary>
365 /// <param name="e">A RegionHandleReplyEventArgs object containing the
366 /// data sent by simulator</param>
367 protected virtual void OnRegionHandleReply(RegionHandleReplyEventArgs e)
368 {
369 EventHandler<RegionHandleReplyEventArgs> handler = m_RegionHandleReply;
370 if (handler != null)
371 handler(this, e);
372 }
373  
374 /// <summary>Thread sync lock object</summary>
375 private readonly object m_RegionHandleReplyLock = new object();
376  
377 /// <summary>Raised in response to a Region lookup</summary>
378 public event EventHandler<RegionHandleReplyEventArgs> RegionHandleReply
379 {
380 add { lock (m_RegionHandleReplyLock) { m_RegionHandleReply += value; } }
381 remove { lock (m_RegionHandleReplyLock) { m_RegionHandleReply -= value; } }
382 }
383  
384 #endregion Delegates
385  
386 /// <summary>Unknown</summary>
387 public float SunPhase { get { return sunPhase; } }
388 /// <summary>Current direction of the sun</summary>
389 public Vector3 SunDirection { get { return sunDirection; } }
390 /// <summary>Current angular velocity of the sun</summary>
391 public Vector3 SunAngVelocity { get { return sunAngVelocity; } }
392 /// <summary>Microseconds since the start of SL 4-hour day</summary>
393 public ulong TimeOfDay { get { return timeOfDay; } }
394  
395 /// <summary>A dictionary of all the regions, indexed by region name</summary>
396 internal Dictionary<string, GridRegion> Regions = new Dictionary<string, GridRegion>();
397 /// <summary>A dictionary of all the regions, indexed by region handle</summary>
398 internal Dictionary<ulong, GridRegion> RegionsByHandle = new Dictionary<ulong, GridRegion>();
399  
400 private GridClient Client;
401 private float sunPhase;
402 private Vector3 sunDirection;
403 private Vector3 sunAngVelocity;
404 private ulong timeOfDay;
405  
406 /// <summary>
407 /// Constructor
408 /// </summary>
409 /// <param name="client">Instance of GridClient object to associate with this GridManager instance</param>
410 public GridManager(GridClient client)
411 {
412 Client = client;
413  
414 //Client.Network.RegisterCallback(PacketType.MapLayerReply, MapLayerReplyHandler);
415 Client.Network.RegisterCallback(PacketType.MapBlockReply, MapBlockReplyHandler);
416 Client.Network.RegisterCallback(PacketType.MapItemReply, MapItemReplyHandler);
417 Client.Network.RegisterCallback(PacketType.SimulatorViewerTimeMessage, SimulatorViewerTimeMessageHandler);
418 Client.Network.RegisterCallback(PacketType.CoarseLocationUpdate, CoarseLocationHandler, false);
419 Client.Network.RegisterCallback(PacketType.RegionIDAndHandleReply, RegionHandleReplyHandler);
420 }
421  
422 /// <summary>
423 ///
424 /// </summary>
425 /// <param name="layer"></param>
426 public void RequestMapLayer(GridLayerType layer)
427 {
428 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("MapLayer");
429  
430 if (url != null)
431 {
432 OSDMap body = new OSDMap();
433 body["Flags"] = OSD.FromInteger((int)layer);
434  
435 CapsClient request = new CapsClient(url);
436 request.OnComplete += new CapsClient.CompleteCallback(MapLayerResponseHandler);
437 request.BeginGetResponse(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
438 }
439 }
440  
441 /// <summary>
442 /// Request a map layer
443 /// </summary>
444 /// <param name="regionName">The name of the region</param>
445 /// <param name="layer">The type of layer</param>
446 public void RequestMapRegion(string regionName, GridLayerType layer)
447 {
448 MapNameRequestPacket request = new MapNameRequestPacket();
449  
450 request.AgentData.AgentID = Client.Self.AgentID;
451 request.AgentData.SessionID = Client.Self.SessionID;
452 request.AgentData.Flags = (uint)layer;
453 request.AgentData.EstateID = 0; // Filled in on the sim
454 request.AgentData.Godlike = false; // Filled in on the sim
455 request.NameData.Name = Utils.StringToBytes(regionName);
456  
457 Client.Network.SendPacket(request);
458 }
459  
460 /// <summary>
461 ///
462 /// </summary>
463 /// <param name="layer"></param>
464 /// <param name="minX"></param>
465 /// <param name="minY"></param>
466 /// <param name="maxX"></param>
467 /// <param name="maxY"></param>
468 /// <param name="returnNonExistent"></param>
469 public void RequestMapBlocks(GridLayerType layer, ushort minX, ushort minY, ushort maxX, ushort maxY,
470 bool returnNonExistent)
471 {
472 MapBlockRequestPacket request = new MapBlockRequestPacket();
473  
474 request.AgentData.AgentID = Client.Self.AgentID;
475 request.AgentData.SessionID = Client.Self.SessionID;
476 request.AgentData.Flags = (uint)layer;
477 request.AgentData.Flags |= (uint)(returnNonExistent ? 0x10000 : 0);
478 request.AgentData.EstateID = 0; // Filled in at the simulator
479 request.AgentData.Godlike = false; // Filled in at the simulator
480  
481 request.PositionData.MinX = minX;
482 request.PositionData.MinY = minY;
483 request.PositionData.MaxX = maxX;
484 request.PositionData.MaxY = maxY;
485  
486 Client.Network.SendPacket(request);
487 }
488  
489 /// <summary>
490 ///
491 /// </summary>
492 /// <param name="regionHandle"></param>
493 /// <param name="item"></param>
494 /// <param name="layer"></param>
495 /// <param name="timeoutMS"></param>
496 /// <returns></returns>
497 public List<MapItem> MapItems(ulong regionHandle, GridItemType item, GridLayerType layer, int timeoutMS)
498 {
499 List<MapItem> itemList = null;
500 AutoResetEvent itemsEvent = new AutoResetEvent(false);
501  
502 EventHandler<GridItemsEventArgs> callback =
503 delegate(object sender, GridItemsEventArgs e)
504 {
505 if (e.Type == GridItemType.AgentLocations)
506 {
507 itemList = e.Items;
508 itemsEvent.Set();
509 }
510 };
511  
512 GridItems += callback;
513  
514 RequestMapItems(regionHandle, item, layer);
515 itemsEvent.WaitOne(timeoutMS, false);
516  
517 GridItems -= callback;
518  
519 return itemList;
520 }
521  
522 /// <summary>
523 ///
524 /// </summary>
525 /// <param name="regionHandle"></param>
526 /// <param name="item"></param>
527 /// <param name="layer"></param>
528 public void RequestMapItems(ulong regionHandle, GridItemType item, GridLayerType layer)
529 {
530 MapItemRequestPacket request = new MapItemRequestPacket();
531 request.AgentData.AgentID = Client.Self.AgentID;
532 request.AgentData.SessionID = Client.Self.SessionID;
533 request.AgentData.Flags = (uint)layer;
534 request.AgentData.Godlike = false; // Filled in on the sim
535 request.AgentData.EstateID = 0; // Filled in on the sim
536  
537 request.RequestData.ItemType = (uint)item;
538 request.RequestData.RegionHandle = regionHandle;
539  
540 Client.Network.SendPacket(request);
541 }
542  
543 /// <summary>
544 /// Request data for all mainland (Linden managed) simulators
545 /// </summary>
546 public void RequestMainlandSims(GridLayerType layer)
547 {
548 RequestMapBlocks(layer, 0, 0, 65535, 65535, false);
549 }
550  
551 /// <summary>
552 /// Request the region handle for the specified region UUID
553 /// </summary>
554 /// <param name="regionID">UUID of the region to look up</param>
555 public void RequestRegionHandle(UUID regionID)
556 {
557 RegionHandleRequestPacket request = new RegionHandleRequestPacket();
558 request.RequestBlock = new RegionHandleRequestPacket.RequestBlockBlock();
559 request.RequestBlock.RegionID = regionID;
560 Client.Network.SendPacket(request);
561 }
562  
563 /// <summary>
564 /// Get grid region information using the region name, this function
565 /// will block until it can find the region or gives up
566 /// </summary>
567 /// <param name="name">Name of sim you're looking for</param>
568 /// <param name="layer">Layer that you are requesting</param>
569 /// <param name="region">Will contain a GridRegion for the sim you're
570 /// looking for if successful, otherwise an empty structure</param>
571 /// <returns>True if the GridRegion was successfully fetched, otherwise
572 /// false</returns>
573 public bool GetGridRegion(string name, GridLayerType layer, out GridRegion region)
574 {
575 if (String.IsNullOrEmpty(name))
576 {
577 Logger.Log("GetGridRegion called with a null or empty region name", Helpers.LogLevel.Error, Client);
578 region = new GridRegion();
579 return false;
580 }
581  
582 if (Regions.ContainsKey(name))
583 {
584 // We already have this GridRegion structure
585 region = Regions[name];
586 return true;
587 }
588 else
589 {
590 AutoResetEvent regionEvent = new AutoResetEvent(false);
591 EventHandler<GridRegionEventArgs> callback =
592 delegate(object sender, GridRegionEventArgs e)
593 {
594 if (e.Region.Name == name)
595 regionEvent.Set();
596 };
597 GridRegion += callback;
598  
599 RequestMapRegion(name, layer);
600 regionEvent.WaitOne(Client.Settings.MAP_REQUEST_TIMEOUT, false);
601  
602 GridRegion -= callback;
603  
604 if (Regions.ContainsKey(name))
605 {
606 // The region was found after our request
607 region = Regions[name];
608 return true;
609 }
610 else
611 {
612 Logger.Log("Couldn't find region " + name, Helpers.LogLevel.Warning, Client);
613 region = new GridRegion();
614 return false;
615 }
616 }
617 }
618  
619 protected void MapLayerResponseHandler(CapsClient client, OSD result, Exception error)
620 {
621 if (result == null)
622 {
623 Logger.Log("MapLayerResponseHandler error: " + error.Message + ": " + error.StackTrace, Helpers.LogLevel.Error, Client);
624 return;
625 }
626 OSDMap body = (OSDMap)result;
627 OSDArray layerData = (OSDArray)body["LayerData"];
628  
629 if (m_GridLayer != null)
630 {
631 for (int i = 0; i < layerData.Count; i++)
632 {
633 OSDMap thisLayerData = (OSDMap)layerData[i];
634  
635 GridLayer layer;
636 layer.Bottom = thisLayerData["Bottom"].AsInteger();
637 layer.Left = thisLayerData["Left"].AsInteger();
638 layer.Top = thisLayerData["Top"].AsInteger();
639 layer.Right = thisLayerData["Right"].AsInteger();
640 layer.ImageID = thisLayerData["ImageID"].AsUUID();
641  
642 OnGridLayer(new GridLayerEventArgs(layer));
643 }
644 }
645  
646 if (body.ContainsKey("MapBlocks"))
647 {
648 // TODO: At one point this will become activated
649 Logger.Log("Got MapBlocks through CAPS, please finish this function!", Helpers.LogLevel.Error, Client);
650 }
651 }
652  
653 /// <summary>Process an incoming packet and raise the appropriate events</summary>
654 /// <param name="sender">The sender</param>
655 /// <param name="e">The EventArgs object containing the packet data</param>
656 protected void MapBlockReplyHandler(object sender, PacketReceivedEventArgs e)
657 {
658 MapBlockReplyPacket map = (MapBlockReplyPacket)e.Packet;
659  
660 foreach (MapBlockReplyPacket.DataBlock block in map.Data)
661 {
662 if (block.X != 0 || block.Y != 0)
663 {
664 GridRegion region;
665  
666 region.X = block.X;
667 region.Y = block.Y;
668 region.Name = Utils.BytesToString(block.Name);
669 // RegionFlags seems to always be zero here?
670 region.RegionFlags = (RegionFlags)block.RegionFlags;
671 region.WaterHeight = block.WaterHeight;
672 region.Agents = block.Agents;
673 region.Access = (SimAccess)block.Access;
674 region.MapImageID = block.MapImageID;
675 region.RegionHandle = Utils.UIntsToLong((uint)(region.X * 256), (uint)(region.Y * 256));
676  
677 lock (Regions)
678 {
679 Regions[region.Name] = region;
680 RegionsByHandle[region.RegionHandle] = region;
681 }
682  
683 if (m_GridRegion != null)
684 {
685 OnGridRegion(new GridRegionEventArgs(region));
686 }
687 }
688 }
689 }
690  
691 /// <summary>Process an incoming packet and raise the appropriate events</summary>
692 /// <param name="sender">The sender</param>
693 /// <param name="e">The EventArgs object containing the packet data</param>
694 protected void MapItemReplyHandler(object sender, PacketReceivedEventArgs e)
695 {
696 if (m_GridItems != null)
697 {
698 MapItemReplyPacket reply = (MapItemReplyPacket)e.Packet;
699 GridItemType type = (GridItemType)reply.RequestData.ItemType;
700 List<MapItem> items = new List<MapItem>();
701  
702 for (int i = 0; i < reply.Data.Length; i++)
703 {
704 string name = Utils.BytesToString(reply.Data[i].Name);
705  
706 switch (type)
707 {
708 case GridItemType.AgentLocations:
709 MapAgentLocation location = new MapAgentLocation();
710 location.GlobalX = reply.Data[i].X;
711 location.GlobalY = reply.Data[i].Y;
712 location.Identifier = name;
713 location.AvatarCount = reply.Data[i].Extra;
714 items.Add(location);
715 break;
716 case GridItemType.Classified:
717 //FIXME:
718 Logger.Log("FIXME", Helpers.LogLevel.Error, Client);
719 break;
720 case GridItemType.LandForSale:
721 MapLandForSale landsale = new MapLandForSale();
722 landsale.GlobalX = reply.Data[i].X;
723 landsale.GlobalY = reply.Data[i].Y;
724 landsale.ID = reply.Data[i].ID;
725 landsale.Name = name;
726 landsale.Size = reply.Data[i].Extra;
727 landsale.Price = reply.Data[i].Extra2;
728 items.Add(landsale);
729 break;
730 case GridItemType.MatureEvent:
731 MapMatureEvent matureEvent = new MapMatureEvent();
732 matureEvent.GlobalX = reply.Data[i].X;
733 matureEvent.GlobalY = reply.Data[i].Y;
734 matureEvent.Description = name;
735 matureEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
736 items.Add(matureEvent);
737 break;
738 case GridItemType.PgEvent:
739 MapPGEvent PGEvent = new MapPGEvent();
740 PGEvent.GlobalX = reply.Data[i].X;
741 PGEvent.GlobalY = reply.Data[i].Y;
742 PGEvent.Description = name;
743 PGEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
744 items.Add(PGEvent);
745 break;
746 case GridItemType.Popular:
747 //FIXME:
748 Logger.Log("FIXME", Helpers.LogLevel.Error, Client);
749 break;
750 case GridItemType.Telehub:
751 MapTelehub teleHubItem = new MapTelehub();
752 teleHubItem.GlobalX = reply.Data[i].X;
753 teleHubItem.GlobalY = reply.Data[i].Y;
754 items.Add(teleHubItem);
755 break;
756 case GridItemType.AdultLandForSale:
757 MapAdultLandForSale adultLandsale = new MapAdultLandForSale();
758 adultLandsale.GlobalX = reply.Data[i].X;
759 adultLandsale.GlobalY = reply.Data[i].Y;
760 adultLandsale.ID = reply.Data[i].ID;
761 adultLandsale.Name = name;
762 adultLandsale.Size = reply.Data[i].Extra;
763 adultLandsale.Price = reply.Data[i].Extra2;
764 items.Add(adultLandsale);
765 break;
766 case GridItemType.AdultEvent:
767 MapAdultEvent adultEvent = new MapAdultEvent();
768 adultEvent.GlobalX = reply.Data[i].X;
769 adultEvent.GlobalY = reply.Data[i].Y;
770 adultEvent.Description = Utils.BytesToString(reply.Data[i].Name);
771 adultEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
772 items.Add(adultEvent);
773 break;
774 default:
775 Logger.Log("Unknown map item type " + type, Helpers.LogLevel.Warning, Client);
776 break;
777 }
778 }
779  
780 OnGridItems(new GridItemsEventArgs(type, items));
781 }
782 }
783  
784 /// <summary>Process an incoming packet and raise the appropriate events</summary>
785 /// <param name="sender">The sender</param>
786 /// <param name="e">The EventArgs object containing the packet data</param>
787 protected void SimulatorViewerTimeMessageHandler(object sender, PacketReceivedEventArgs e)
788 {
789 SimulatorViewerTimeMessagePacket time = (SimulatorViewerTimeMessagePacket)e.Packet;
790  
791 sunPhase = time.TimeInfo.SunPhase;
792 sunDirection = time.TimeInfo.SunDirection;
793 sunAngVelocity = time.TimeInfo.SunAngVelocity;
794 timeOfDay = time.TimeInfo.UsecSinceStart;
795 // TODO: Does anyone have a use for the time stuff?
796 }
797  
798 /// <summary>Process an incoming packet and raise the appropriate events</summary>
799 /// <param name="sender">The sender</param>
800 /// <param name="e">The EventArgs object containing the packet data</param>
801 protected void CoarseLocationHandler(object sender, PacketReceivedEventArgs e)
802 {
803 CoarseLocationUpdatePacket coarse = (CoarseLocationUpdatePacket)e.Packet;
804  
805 // populate a dictionary from the packet, for local use
806 Dictionary<UUID, Vector3> coarseEntries = new Dictionary<UUID, Vector3>();
807 for (int i = 0; i < coarse.AgentData.Length; i++)
808 {
809 if(coarse.Location.Length > 0)
810 coarseEntries[coarse.AgentData[i].AgentID] = new Vector3((int)coarse.Location[i].X, (int)coarse.Location[i].Y, (int)coarse.Location[i].Z * 4);
811  
812 // the friend we are tracking on radar
813 if (i == coarse.Index.Prey)
814 e.Simulator.preyID = coarse.AgentData[i].AgentID;
815 }
816  
817 // find stale entries (people who left the sim)
818 List<UUID> removedEntries = e.Simulator.avatarPositions.FindAll(delegate(UUID findID) { return !coarseEntries.ContainsKey(findID); });
819  
820 // anyone who was not listed in the previous update
821 List<UUID> newEntries = new List<UUID>();
822  
823 lock (e.Simulator.avatarPositions.Dictionary)
824 {
825 // remove stale entries
826 foreach(UUID trackedID in removedEntries)
827 e.Simulator.avatarPositions.Dictionary.Remove(trackedID);
828  
829 // add or update tracked info, and record who is new
830 foreach (KeyValuePair<UUID, Vector3> entry in coarseEntries)
831 {
832 if (!e.Simulator.avatarPositions.Dictionary.ContainsKey(entry.Key))
833 newEntries.Add(entry.Key);
834  
835 e.Simulator.avatarPositions.Dictionary[entry.Key] = entry.Value;
836 }
837 }
838  
839 if (m_CoarseLocationUpdate != null)
840 {
841 WorkPool.QueueUserWorkItem(delegate(object o)
842 { OnCoarseLocationUpdate(new CoarseLocationUpdateEventArgs(e.Simulator, newEntries, removedEntries)); });
843 }
844 }
845  
846 /// <summary>Process an incoming packet and raise the appropriate events</summary>
847 /// <param name="sender">The sender</param>
848 /// <param name="e">The EventArgs object containing the packet data</param>
849 protected void RegionHandleReplyHandler(object sender, PacketReceivedEventArgs e)
850 {
851 if (m_RegionHandleReply != null)
852 {
853 RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)e.Packet;
854 OnRegionHandleReply(new RegionHandleReplyEventArgs(reply.ReplyBlock.RegionID, reply.ReplyBlock.RegionHandle));
855 }
856 }
857  
858 }
859 #region EventArgs classes
860  
861 public class CoarseLocationUpdateEventArgs : EventArgs
862 {
863 private readonly Simulator m_Simulator;
864 private readonly List<UUID> m_NewEntries;
865 private readonly List<UUID> m_RemovedEntries;
866  
867 public Simulator Simulator { get { return m_Simulator; } }
868 public List<UUID> NewEntries { get { return m_NewEntries; } }
869 public List<UUID> RemovedEntries { get { return m_RemovedEntries; } }
870  
871 public CoarseLocationUpdateEventArgs(Simulator simulator, List<UUID> newEntries, List<UUID> removedEntries)
872 {
873 this.m_Simulator = simulator;
874 this.m_NewEntries = newEntries;
875 this.m_RemovedEntries = removedEntries;
876 }
877 }
878  
879 public class GridRegionEventArgs : EventArgs
880 {
881 private readonly GridRegion m_Region;
882 public GridRegion Region { get { return m_Region; } }
883  
884 public GridRegionEventArgs(GridRegion region)
885 {
886 this.m_Region = region;
887 }
888 }
889  
890 public class GridLayerEventArgs : EventArgs
891 {
892 private readonly GridLayer m_Layer;
893  
894 public GridLayer Layer { get { return m_Layer; } }
895  
896 public GridLayerEventArgs(GridLayer layer)
897 {
898 this.m_Layer = layer;
899 }
900 }
901  
902 public class GridItemsEventArgs : EventArgs
903 {
904 private readonly GridItemType m_Type;
905 private readonly List<MapItem> m_Items;
906  
907 public GridItemType Type { get { return m_Type; } }
908 public List<MapItem> Items { get { return m_Items; } }
909  
910 public GridItemsEventArgs(GridItemType type, List<MapItem> items)
911 {
912 this.m_Type = type;
913 this.m_Items = items;
914 }
915 }
916  
917 public class RegionHandleReplyEventArgs : EventArgs
918 {
919 private readonly UUID m_RegionID;
920 private readonly ulong m_RegionHandle;
921  
922 public UUID RegionID { get { return m_RegionID; } }
923 public ulong RegionHandle { get { return m_RegionHandle; } }
924  
925 public RegionHandleReplyEventArgs(UUID regionID, ulong regionHandle)
926 {
927 this.m_RegionID = regionID;
928 this.m_RegionHandle = regionHandle;
929 }
930 }
931  
932 #endregion
933 }