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.Threading;
29 using System.Reflection;
30 using System.Collections.Generic;
31 using OpenMetaverse.Http;
32 using OpenMetaverse.Packets;
33 using OpenMetaverse.Interfaces;
34 using OpenMetaverse.StructuredData;
35 using OpenMetaverse.Messages.Linden;
36  
37 namespace OpenMetaverse
38 {
39 #region Enums
40  
41 /// <summary>
42 /// Type of return to use when returning objects from a parcel
43 /// </summary>
44 public enum ObjectReturnType : uint
45 {
46 /// <summary></summary>
47 None = 0,
48 /// <summary>Return objects owned by parcel owner</summary>
49 Owner = 1 << 1,
50 /// <summary>Return objects set to group</summary>
51 Group = 1 << 2,
52 /// <summary>Return objects not owned by parcel owner or set to group</summary>
53 Other = 1 << 3,
54 /// <summary>Return a specific list of objects on parcel</summary>
55 List = 1 << 4,
56 /// <summary>Return objects that are marked for-sale</summary>
57 Sell = 1 << 5
58 }
59  
60 /// <summary>
61 /// Blacklist/Whitelist flags used in parcels Access List
62 /// </summary>
63 public enum ParcelAccessFlags : uint
64 {
65 /// <summary>Agent is denied access</summary>
66 NoAccess = 0,
67 /// <summary>Agent is granted access</summary>
68 Access = 1
69 }
70  
71 /// <summary>
72 /// The result of a request for parcel properties
73 /// </summary>
74 public enum ParcelResult : int
75 {
76 /// <summary>No matches were found for the request</summary>
77 NoData = -1,
78 /// <summary>Request matched a single parcel</summary>
79 Single = 0,
80 /// <summary>Request matched multiple parcels</summary>
81 Multiple = 1
82 }
83  
84 /// <summary>
85 /// Flags used in the ParcelAccessListRequest packet to specify whether
86 /// we want the access list (whitelist), ban list (blacklist), or both
87 /// </summary>
88 [Flags]
89 public enum AccessList : uint
90 {
91 /// <summary>Request the access list</summary>
92 Access = 1 << 0,
93 /// <summary>Request the ban list</summary>
94 Ban = 1 << 1,
95 /// <summary>Request both White and Black lists</summary>
96 Both = Access | Ban
97 }
98  
99 /// <summary>
100 /// Sequence ID in ParcelPropertiesReply packets (sent when avatar
101 /// tries to cross a parcel border)
102 /// </summary>
103 public enum ParcelPropertiesStatus : int
104 {
105 /// <summary>Parcel is currently selected</summary>
106 ParcelSelected = -10000,
107 /// <summary>Parcel restricted to a group the avatar is not a
108 /// member of</summary>
109 CollisionNotInGroup = -20000,
110 /// <summary>Avatar is banned from the parcel</summary>
111 CollisionBanned = -30000,
112 /// <summary>Parcel is restricted to an access list that the
113 /// avatar is not on</summary>
114 CollisionNotOnAccessList = -40000,
115 /// <summary>Response to hovering over a parcel</summary>
116 HoveredOverParcel = -50000
117 }
118  
119 /// <summary>
120 /// The tool to use when modifying terrain levels
121 /// </summary>
122 public enum TerraformAction : byte
123 {
124 /// <summary>Level the terrain</summary>
125 Level = 0,
126 /// <summary>Raise the terrain</summary>
127 Raise = 1,
128 /// <summary>Lower the terrain</summary>
129 Lower = 2,
130 /// <summary>Smooth the terrain</summary>
131 Smooth = 3,
132 /// <summary>Add random noise to the terrain</summary>
133 Noise = 4,
134 /// <summary>Revert terrain to simulator default</summary>
135 Revert = 5
136 }
137  
138 /// <summary>
139 /// The tool size to use when changing terrain levels
140 /// </summary>
141 public enum TerraformBrushSize : byte
142 {
143 /// <summary>Small</summary>
144 Small = 1,
145 /// <summary>Medium</summary>
146 Medium = 2,
147 /// <summary>Large</summary>
148 Large = 4
149 }
150  
151 /// <summary>
152 /// Reasons agent is denied access to a parcel on the simulator
153 /// </summary>
154 public enum AccessDeniedReason : byte
155 {
156 /// <summary>Agent is not denied, access is granted</summary>
157 NotDenied = 0,
158 /// <summary>Agent is not a member of the group set for the parcel, or which owns the parcel</summary>
159 NotInGroup = 1,
160 /// <summary>Agent is not on the parcels specific allow list</summary>
161 NotOnAllowList = 2,
162 /// <summary>Agent is on the parcels ban list</summary>
163 BannedFromParcel = 3,
164 /// <summary>Unknown</summary>
165 NoAccess = 4,
166 /// <summary>Agent is not age verified and parcel settings deny access to non age verified avatars</summary>
167 NotAgeVerified = 5
168 }
169  
170 /// <summary>
171 /// Parcel overlay type. This is used primarily for highlighting and
172 /// coloring which is why it is a single integer instead of a set of
173 /// flags
174 /// </summary>
175 /// <remarks>These values seem to be poorly thought out. The first three
176 /// bits represent a single value, not flags. For example Auction (0x05) is
177 /// not a combination of OwnedByOther (0x01) and ForSale(0x04). However,
178 /// the BorderWest and BorderSouth values are bit flags that get attached
179 /// to the value stored in the first three bits. Bits four, five, and six
180 /// are unused</remarks>
181 [Flags]
182 public enum ParcelOverlayType : byte
183 {
184 /// <summary>Public land</summary>
185 Public = 0,
186 /// <summary>Land is owned by another avatar</summary>
187 OwnedByOther = 1,
188 /// <summary>Land is owned by a group</summary>
189 OwnedByGroup = 2,
190 /// <summary>Land is owned by the current avatar</summary>
191 OwnedBySelf = 3,
192 /// <summary>Land is for sale</summary>
193 ForSale = 4,
194 /// <summary>Land is being auctioned</summary>
195 Auction = 5,
196 /// <summary>Land is private</summary>
197 Private = 32,
198 /// <summary>To the west of this area is a parcel border</summary>
199 BorderWest = 64,
200 /// <summary>To the south of this area is a parcel border</summary>
201 BorderSouth = 128
202 }
203  
204 /// <summary>
205 /// Various parcel properties
206 /// </summary>
207 [Flags]
208 public enum ParcelFlags : uint
209 {
210 /// <summary>No flags set</summary>
211 None = 0,
212 /// <summary>Allow avatars to fly (a client-side only restriction)</summary>
213 AllowFly = 1 << 0,
214 /// <summary>Allow foreign scripts to run</summary>
215 AllowOtherScripts = 1 << 1,
216 /// <summary>This parcel is for sale</summary>
217 ForSale = 1 << 2,
218 /// <summary>Allow avatars to create a landmark on this parcel</summary>
219 AllowLandmark = 1 << 3,
220 /// <summary>Allows all avatars to edit the terrain on this parcel</summary>
221 AllowTerraform = 1 << 4,
222 /// <summary>Avatars have health and can take damage on this parcel.
223 /// If set, avatars can be killed and sent home here</summary>
224 AllowDamage = 1 << 5,
225 /// <summary>Foreign avatars can create objects here</summary>
226 CreateObjects = 1 << 6,
227 /// <summary>All objects on this parcel can be purchased</summary>
228 ForSaleObjects = 1 << 7,
229 /// <summary>Access is restricted to a group</summary>
230 UseAccessGroup = 1 << 8,
231 /// <summary>Access is restricted to a whitelist</summary>
232 UseAccessList = 1 << 9,
233 /// <summary>Ban blacklist is enabled</summary>
234 UseBanList = 1 << 10,
235 /// <summary>Unknown</summary>
236 UsePassList = 1 << 11,
237 /// <summary>List this parcel in the search directory</summary>
238 ShowDirectory = 1 << 12,
239 /// <summary>Allow personally owned parcels to be deeded to group</summary>
240 AllowDeedToGroup = 1 << 13,
241 /// <summary>If Deeded, owner contributes required tier to group parcel is deeded to</summary>
242 ContributeWithDeed = 1 << 14,
243 /// <summary>Restrict sounds originating on this parcel to the
244 /// parcel boundaries</summary>
245 SoundLocal = 1 << 15,
246 /// <summary>Objects on this parcel are sold when the land is
247 /// purchsaed</summary>
248 SellParcelObjects = 1 << 16,
249 /// <summary>Allow this parcel to be published on the web</summary>
250 AllowPublish = 1 << 17,
251 /// <summary>The information for this parcel is mature content</summary>
252 MaturePublish = 1 << 18,
253 /// <summary>The media URL is an HTML page</summary>
254 UrlWebPage = 1 << 19,
255 /// <summary>The media URL is a raw HTML string</summary>
256 UrlRawHtml = 1 << 20,
257 /// <summary>Restrict foreign object pushes</summary>
258 RestrictPushObject = 1 << 21,
259 /// <summary>Ban all non identified/transacted avatars</summary>
260 DenyAnonymous = 1 << 22,
261 // <summary>Ban all identified avatars [OBSOLETE]</summary>
262 //[Obsolete]
263 // This was obsoleted in 1.19.0 but appears to be recycled and is used on linden homes parcels
264 LindenHome = 1 << 23,
265 // <summary>Ban all transacted avatars [OBSOLETE]</summary>
266 //[Obsolete]
267 //DenyTransacted = 1 << 24,
268 /// <summary>Allow group-owned scripts to run</summary>
269 AllowGroupScripts = 1 << 25,
270 /// <summary>Allow object creation by group members or group
271 /// objects</summary>
272 CreateGroupObjects = 1 << 26,
273 /// <summary>Allow all objects to enter this parcel</summary>
274 AllowAPrimitiveEntry = 1 << 27,
275 /// <summary>Only allow group and owner objects to enter this parcel</summary>
276 AllowGroupObjectEntry = 1 << 28,
277 /// <summary>Voice Enabled on this parcel</summary>
278 AllowVoiceChat = 1 << 29,
279 /// <summary>Use Estate Voice channel for Voice on this parcel</summary>
280 UseEstateVoiceChan = 1 << 30,
281 /// <summary>Deny Age Unverified Users</summary>
282 DenyAgeUnverified = 1U << 31
283 }
284  
285 /// <summary>
286 /// Parcel ownership status
287 /// </summary>
288 public enum ParcelStatus : sbyte
289 {
290 /// <summary>Placeholder</summary>
291 None = -1,
292 /// <summary>Parcel is leased (owned) by an avatar or group</summary>
293 Leased = 0,
294 /// <summary>Parcel is in process of being leased (purchased) by an avatar or group</summary>
295 LeasePending = 1,
296 /// <summary>Parcel has been abandoned back to Governor Linden</summary>
297 Abandoned = 2
298 }
299  
300 /// <summary>
301 /// Category parcel is listed in under search
302 /// </summary>
303 public enum ParcelCategory : sbyte
304 {
305 /// <summary>No assigned category</summary>
306 None = 0,
307 /// <summary>Linden Infohub or public area</summary>
308 Linden,
309 /// <summary>Adult themed area</summary>
310 Adult,
311 /// <summary>Arts and Culture</summary>
312 Arts,
313 /// <summary>Business</summary>
314 Business,
315 /// <summary>Educational</summary>
316 Educational,
317 /// <summary>Gaming</summary>
318 Gaming,
319 /// <summary>Hangout or Club</summary>
320 Hangout,
321 /// <summary>Newcomer friendly</summary>
322 Newcomer,
323 /// <summary>Parks and Nature</summary>
324 Park,
325 /// <summary>Residential</summary>
326 Residential,
327 /// <summary>Shopping</summary>
328 Shopping,
329 /// <summary>Not Used?</summary>
330 Stage,
331 /// <summary>Other</summary>
332 Other,
333 /// <summary>Not an actual category, only used for queries</summary>
334 Any = -1
335 }
336  
337 /// <summary>
338 /// Type of teleport landing for a parcel
339 /// </summary>
340 public enum LandingType : byte
341 {
342 /// <summary>Unset, simulator default</summary>
343 None = 0,
344 /// <summary>Specific landing point set for this parcel</summary>
345 LandingPoint = 1,
346 /// <summary>No landing point set, direct teleports enabled for
347 /// this parcel</summary>
348 Direct = 2
349 }
350  
351 /// <summary>
352 /// Parcel Media Command used in ParcelMediaCommandMessage
353 /// </summary>
354 public enum ParcelMediaCommand : uint
355 {
356 /// <summary>Stop the media stream and go back to the first frame</summary>
357 Stop = 0,
358 /// <summary>Pause the media stream (stop playing but stay on current frame)</summary>
359 Pause,
360 /// <summary>Start the current media stream playing and stop when the end is reached</summary>
361 Play,
362 /// <summary>Start the current media stream playing,
363 /// loop to the beginning when the end is reached and continue to play</summary>
364 Loop,
365 /// <summary>Specifies the texture to replace with video</summary>
366 /// <remarks>If passing the key of a texture, it must be explicitly typecast as a key,
367 /// not just passed within double quotes.</remarks>
368 Texture,
369 /// <summary>Specifies the movie URL (254 characters max)</summary>
370 URL,
371 /// <summary>Specifies the time index at which to begin playing</summary>
372 Time,
373 /// <summary>Specifies a single agent to apply the media command to</summary>
374 Agent,
375 /// <summary>Unloads the stream. While the stop command sets the texture to the first frame of the movie,
376 /// unload resets it to the real texture that the movie was replacing.</summary>
377 Unload,
378 /// <summary>Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties
379 /// (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter.</summary>
380 AutoAlign,
381 /// <summary>Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only).
382 /// Use "text/html" for HTML.</summary>
383 Type,
384 /// <summary>Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only).</summary>
385 /// <remarks>This might still not be working</remarks>
386 Size,
387 /// <summary>Sets a description for the media being displayed (1.19.1 RC0 and later only).</summary>
388 Desc
389 }
390  
391 #endregion Enums
392  
393 #region Structs
394  
395 /// <summary>
396 /// Some information about a parcel of land returned from a DirectoryManager search
397 /// </summary>
398 public struct ParcelInfo
399 {
400 /// <summary>Global Key of record</summary>
401 public UUID ID;
402 /// <summary>Parcel Owners <seealso cref="UUID"/></summary>
403 public UUID OwnerID;
404 /// <summary>Name field of parcel, limited to 128 characters</summary>
405 public string Name;
406 /// <summary>Description field of parcel, limited to 256 characters</summary>
407 public string Description;
408 /// <summary>Total Square meters of parcel</summary>
409 public int ActualArea;
410 /// <summary>Total area billable as Tier, for group owned land this will be 10% less than ActualArea</summary>
411 public int BillableArea;
412 /// <summary>True of parcel is in Mature simulator</summary>
413 public bool Mature;
414 /// <summary>Grid global X position of parcel</summary>
415 public float GlobalX;
416 /// <summary>Grid global Y position of parcel</summary>
417 public float GlobalY;
418 /// <summary>Grid global Z position of parcel (not used)</summary>
419 public float GlobalZ;
420 /// <summary>Name of simulator parcel is located in</summary>
421 public string SimName;
422 /// <summary>Texture <seealso cref="T:OpenMetaverse.UUID"/> of parcels display picture</summary>
423 public UUID SnapshotID;
424 /// <summary>Float representing calculated traffic based on time spent on parcel by avatars</summary>
425 public float Dwell;
426 /// <summary>Sale price of parcel (not used)</summary>
427 public int SalePrice;
428 /// <summary>Auction ID of parcel</summary>
429 public int AuctionID;
430 }
431  
432 /// <summary>
433 /// Parcel Media Information
434 /// </summary>
435 public struct ParcelMedia
436 {
437 /// <summary>A byte, if 0x1 viewer should auto scale media to fit object</summary>
438 public bool MediaAutoScale;
439 /// <summary>A boolean, if true the viewer should loop the media</summary>
440 public bool MediaLoop;
441 /// <summary>The Asset UUID of the Texture which when applied to a
442 /// primitive will display the media</summary>
443 public UUID MediaID;
444 /// <summary>A URL which points to any Quicktime supported media type</summary>
445 public string MediaURL;
446 /// <summary>A description of the media</summary>
447 public string MediaDesc;
448 /// <summary>An Integer which represents the height of the media</summary>
449 public int MediaHeight;
450 /// <summary>An integer which represents the width of the media</summary>
451 public int MediaWidth;
452 /// <summary>A string which contains the mime type of the media</summary>
453 public string MediaType;
454 }
455  
456 #endregion Structs
457  
458 #region Parcel Class
459  
460 /// <summary>
461 /// Parcel of land, a portion of virtual real estate in a simulator
462 /// </summary>
463 public class Parcel
464 {
465 /// <summary>The total number of contiguous 4x4 meter blocks your agent owns within this parcel</summary>
466 public int SelfCount;
467 /// <summary>The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own</summary>
468 public int OtherCount;
469 /// <summary>Deprecated, Value appears to always be 0</summary>
470 public int PublicCount;
471 /// <summary>Simulator-local ID of this parcel</summary>
472 public int LocalID;
473 /// <summary>UUID of the owner of this parcel</summary>
474 public UUID OwnerID;
475 /// <summary>Whether the land is deeded to a group or not</summary>
476 public bool IsGroupOwned;
477 /// <summary></summary>
478 public uint AuctionID;
479 /// <summary>Date land was claimed</summary>
480 public DateTime ClaimDate;
481 /// <summary>Appears to always be zero</summary>
482 public int ClaimPrice;
483 /// <summary>This field is no longer used</summary>
484 public int RentPrice;
485 /// <summary>Minimum corner of the axis-aligned bounding box for this
486 /// parcel</summary>
487 public Vector3 AABBMin;
488 /// <summary>Maximum corner of the axis-aligned bounding box for this
489 /// parcel</summary>
490 public Vector3 AABBMax;
491 /// <summary>Bitmap describing land layout in 4x4m squares across the
492 /// entire region</summary>
493 public byte[] Bitmap;
494 /// <summary>Total parcel land area</summary>
495 public int Area;
496 /// <summary></summary>
497 public ParcelStatus Status;
498 /// <summary>Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used</summary>
499 public int SimWideMaxPrims;
500 /// <summary>Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel
501 /// owned by the agent or group that owns this parcel</summary>
502 public int SimWideTotalPrims;
503 /// <summary>Maximum number of primitives this parcel supports</summary>
504 public int MaxPrims;
505 /// <summary>Total number of primitives on this parcel</summary>
506 public int TotalPrims;
507 /// <summary>For group-owned parcels this indicates the total number of prims deeded to the group,
508 /// for parcels owned by an individual this inicates the number of prims owned by the individual</summary>
509 public int OwnerPrims;
510 /// <summary>Total number of primitives owned by the parcel group on
511 /// this parcel, or for parcels owned by an individual with a group set the
512 /// total number of prims set to that group.</summary>
513 public int GroupPrims;
514 /// <summary>Total number of prims owned by other avatars that are not set to group, or not the parcel owner</summary>
515 public int OtherPrims;
516 /// <summary>A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect
517 /// the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed</summary>
518 public float ParcelPrimBonus;
519 /// <summary>Autoreturn value in minutes for others' objects</summary>
520 public int OtherCleanTime;
521 /// <summary></summary>
522 public ParcelFlags Flags;
523 /// <summary>Sale price of the parcel, only useful if ForSale is set</summary>
524 /// <remarks>The SalePrice will remain the same after an ownership
525 /// transfer (sale), so it can be used to see the purchase price after
526 /// a sale if the new owner has not changed it</remarks>
527 public int SalePrice;
528 /// <summary>Parcel Name</summary>
529 public string Name;
530 /// <summary>Parcel Description</summary>
531 public string Desc;
532 /// <summary>URL For Music Stream</summary>
533 public string MusicURL;
534 /// <summary></summary>
535 public UUID GroupID;
536 /// <summary>Price for a temporary pass</summary>
537 public int PassPrice;
538 /// <summary>How long is pass valid for</summary>
539 public float PassHours;
540 /// <summary></summary>
541 public ParcelCategory Category;
542 /// <summary>Key of authorized buyer</summary>
543 public UUID AuthBuyerID;
544 /// <summary>Key of parcel snapshot</summary>
545 public UUID SnapshotID;
546 /// <summary>The landing point location</summary>
547 public Vector3 UserLocation;
548 /// <summary>The landing point LookAt</summary>
549 public Vector3 UserLookAt;
550 /// <summary>The type of landing enforced from the <see cref="LandingType"/> enum</summary>
551 public LandingType Landing;
552 /// <summary></summary>
553 public float Dwell;
554 /// <summary></summary>
555 public bool RegionDenyAnonymous;
556 /// <summary></summary>
557 public bool RegionPushOverride;
558 /// <summary>Access list of who is whitelisted on this
559 /// parcel</summary>
560 public List<ParcelManager.ParcelAccessEntry> AccessWhiteList;
561 /// <summary>Access list of who is blacklisted on this
562 /// parcel</summary>
563 public List<ParcelManager.ParcelAccessEntry> AccessBlackList;
564 /// <summary>TRUE of region denies access to age unverified users</summary>
565 public bool RegionDenyAgeUnverified;
566 /// <summary>true to obscure (hide) media url</summary>
567 public bool ObscureMedia;
568 /// <summary>true to obscure (hide) music url</summary>
569 public bool ObscureMusic;
570 /// <summary>A struct containing media details</summary>
571 public ParcelMedia Media;
572  
573 /// <summary>
574 /// Displays a parcel object in string format
575 /// </summary>
576 /// <returns>string containing key=value pairs of a parcel object</returns>
577 public override string ToString()
578 {
579 string result = "";
580 Type parcelType = this.GetType();
581 FieldInfo[] fields = parcelType.GetFields();
582 foreach (FieldInfo field in fields)
583 {
584 result += (field.Name + " = " + field.GetValue(this) + " ");
585 }
586 return result;
587 }
588 /// <summary>
589 /// Defalt constructor
590 /// </summary>
591 /// <param name="localID">Local ID of this parcel</param>
592 public Parcel(int localID)
593 {
594 LocalID = localID;
595 ClaimDate = Utils.Epoch;
596 Bitmap = Utils.EmptyBytes;
597 Name = String.Empty;
598 Desc = String.Empty;
599 MusicURL = String.Empty;
600 AccessWhiteList = new List<ParcelManager.ParcelAccessEntry>(0);
601 AccessBlackList = new List<ParcelManager.ParcelAccessEntry>(0);
602 Media = new ParcelMedia();
603 }
604  
605 /// <summary>
606 /// Update the simulator with any local changes to this Parcel object
607 /// </summary>
608 /// <param name="simulator">Simulator to send updates to</param>
609 /// <param name="wantReply">Whether we want the simulator to confirm
610 /// the update with a reply packet or not</param>
611 public void Update(Simulator simulator, bool wantReply)
612 {
613 Uri url = simulator.Caps.CapabilityURI("ParcelPropertiesUpdate");
614  
615 if (url != null)
616 {
617 ParcelPropertiesUpdateMessage req = new ParcelPropertiesUpdateMessage();
618 req.AuthBuyerID = this.AuthBuyerID;
619 req.Category = this.Category;
620 req.Desc = this.Desc;
621 req.GroupID = this.GroupID;
622 req.Landing = this.Landing;
623 req.LocalID = this.LocalID;
624 req.MediaAutoScale = this.Media.MediaAutoScale;
625 req.MediaDesc = this.Media.MediaDesc;
626 req.MediaHeight = this.Media.MediaHeight;
627 req.MediaID = this.Media.MediaID;
628 req.MediaLoop = this.Media.MediaLoop;
629 req.MediaType = this.Media.MediaType;
630 req.MediaURL = this.Media.MediaURL;
631 req.MediaWidth = this.Media.MediaWidth;
632 req.MusicURL = this.MusicURL;
633 req.Name = this.Name;
634 req.ObscureMedia = this.ObscureMedia;
635 req.ObscureMusic = this.ObscureMusic;
636 req.ParcelFlags = this.Flags;
637 req.PassHours = this.PassHours;
638 req.PassPrice = (uint)this.PassPrice;
639 req.SalePrice = (uint)this.SalePrice;
640 req.SnapshotID = this.SnapshotID;
641 req.UserLocation = this.UserLocation;
642 req.UserLookAt = this.UserLookAt;
643  
644 OSDMap body = req.Serialize();
645  
646 CapsClient capsPost = new CapsClient(url);
647 capsPost.BeginGetResponse(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
648 }
649 else
650 {
651 ParcelPropertiesUpdatePacket request = new ParcelPropertiesUpdatePacket();
652  
653 request.AgentData.AgentID = simulator.Client.Self.AgentID;
654 request.AgentData.SessionID = simulator.Client.Self.SessionID;
655  
656 request.ParcelData.LocalID = this.LocalID;
657  
658 request.ParcelData.AuthBuyerID = this.AuthBuyerID;
659 request.ParcelData.Category = (byte)this.Category;
660 request.ParcelData.Desc = Utils.StringToBytes(this.Desc);
661 request.ParcelData.GroupID = this.GroupID;
662 request.ParcelData.LandingType = (byte)this.Landing;
663 request.ParcelData.MediaAutoScale = (this.Media.MediaAutoScale) ? (byte)0x1 : (byte)0x0;
664 request.ParcelData.MediaID = this.Media.MediaID;
665 request.ParcelData.MediaURL = Utils.StringToBytes(this.Media.MediaURL.ToString());
666 request.ParcelData.MusicURL = Utils.StringToBytes(this.MusicURL.ToString());
667 request.ParcelData.Name = Utils.StringToBytes(this.Name);
668 if (wantReply) request.ParcelData.Flags = 1;
669 request.ParcelData.ParcelFlags = (uint)this.Flags;
670 request.ParcelData.PassHours = this.PassHours;
671 request.ParcelData.PassPrice = this.PassPrice;
672 request.ParcelData.SalePrice = this.SalePrice;
673 request.ParcelData.SnapshotID = this.SnapshotID;
674 request.ParcelData.UserLocation = this.UserLocation;
675 request.ParcelData.UserLookAt = this.UserLookAt;
676  
677 simulator.SendPacket(request);
678 }
679  
680 UpdateOtherCleanTime(simulator);
681  
682 }
683  
684 /// <summary>
685 /// Set Autoreturn time
686 /// </summary>
687 /// <param name="simulator">Simulator to send the update to</param>
688 public void UpdateOtherCleanTime(Simulator simulator)
689 {
690 ParcelSetOtherCleanTimePacket request = new ParcelSetOtherCleanTimePacket();
691 request.AgentData.AgentID = simulator.Client.Self.AgentID;
692 request.AgentData.SessionID = simulator.Client.Self.SessionID;
693 request.ParcelData.LocalID = this.LocalID;
694 request.ParcelData.OtherCleanTime = this.OtherCleanTime;
695  
696 simulator.SendPacket(request);
697 }
698 }
699  
700 #endregion Parcel Class
701  
702 /// <summary>
703 /// Parcel (subdivided simulator lots) subsystem
704 /// </summary>
705 public class ParcelManager
706 {
707 #region Structs
708  
709 /// <summary>
710 /// Parcel Accesslist
711 /// </summary>
712 public struct ParcelAccessEntry
713 {
714 /// <summary>Agents <seealso cref="T:OpenMetaverse.UUID"/></summary>
715 public UUID AgentID;
716 /// <summary></summary>
717 public DateTime Time;
718 /// <summary>Flags for specific entry in white/black lists</summary>
719 public AccessList Flags;
720 }
721  
722 /// <summary>
723 /// Owners of primitives on parcel
724 /// </summary>
725 public struct ParcelPrimOwners
726 {
727 /// <summary>Prim Owners <seealso cref="T:OpenMetaverse.UUID"/></summary>
728 public UUID OwnerID;
729 /// <summary>True of owner is group</summary>
730 public bool IsGroupOwned;
731 /// <summary>Total count of prims owned by OwnerID</summary>
732 public int Count;
733 /// <summary>true of OwnerID is currently online and is not a group</summary>
734 public bool OnlineStatus;
735 /// <summary>The date of the most recent prim left by OwnerID</summary>
736 public DateTime NewestPrim;
737 }
738  
739 #endregion Structs
740  
741 #region Delegates
742 /// <summary>
743 /// Called once parcel resource usage information has been collected
744 /// </summary>
745 /// <param name="success">Indicates if operation was successfull</param>
746 /// <param name="info">Parcel resource usage information</param>
747 public delegate void LandResourcesCallback(bool success, LandResourcesInfo info);
748  
749 /// <summary>The event subscribers. null if no subcribers</summary>
750 private EventHandler<ParcelDwellReplyEventArgs> m_DwellReply;
751  
752 /// <summary>Raises the ParcelDwellReply event</summary>
753 /// <param name="e">A ParcelDwellReplyEventArgs object containing the
754 /// data returned from the simulator</param>
755 protected virtual void OnParcelDwellReply(ParcelDwellReplyEventArgs e)
756 {
757 EventHandler<ParcelDwellReplyEventArgs> handler = m_DwellReply;
758 if (handler != null)
759 handler(this, e);
760 }
761  
762 /// <summary>Thread sync lock object</summary>
763 private readonly object m_DwellReplyLock = new object();
764  
765 /// <summary>Raised when the simulator responds to a <see cref="RequestDwell"/> request</summary>
766 public event EventHandler<ParcelDwellReplyEventArgs> ParcelDwellReply
767 {
768 add { lock (m_DwellReplyLock) { m_DwellReply += value; } }
769 remove { lock (m_DwellReplyLock) { m_DwellReply -= value; } }
770 }
771  
772 /// <summary>The event subscribers. null if no subcribers</summary>
773 private EventHandler<ParcelInfoReplyEventArgs> m_ParcelInfo;
774  
775 /// <summary>Raises the ParcelInfoReply event</summary>
776 /// <param name="e">A ParcelInfoReplyEventArgs object containing the
777 /// data returned from the simulator</param>
778 protected virtual void OnParcelInfoReply(ParcelInfoReplyEventArgs e)
779 {
780 EventHandler<ParcelInfoReplyEventArgs> handler = m_ParcelInfo;
781 if (handler != null)
782 handler(this, e);
783 }
784  
785 /// <summary>Thread sync lock object</summary>
786 private readonly object m_ParcelInfoLock = new object();
787  
788 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelInfo"/> request</summary>
789 public event EventHandler<ParcelInfoReplyEventArgs> ParcelInfoReply
790 {
791 add { lock (m_ParcelInfoLock) { m_ParcelInfo += value; } }
792 remove { lock (m_ParcelInfoLock) { m_ParcelInfo -= value; } }
793 }
794  
795 /// <summary>The event subscribers. null if no subcribers</summary>
796 private EventHandler<ParcelPropertiesEventArgs> m_ParcelProperties;
797  
798 /// <summary>Raises the ParcelProperties event</summary>
799 /// <param name="e">A ParcelPropertiesEventArgs object containing the
800 /// data returned from the simulator</param>
801 protected virtual void OnParcelProperties(ParcelPropertiesEventArgs e)
802 {
803 EventHandler<ParcelPropertiesEventArgs> handler = m_ParcelProperties;
804 if (handler != null)
805 handler(this, e);
806 }
807  
808 /// <summary>Thread sync lock object</summary>
809 private readonly object m_ParcelPropertiesLock = new object();
810  
811 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelProperties"/> request</summary>
812 public event EventHandler<ParcelPropertiesEventArgs> ParcelProperties
813 {
814 add { lock (m_ParcelPropertiesLock) { m_ParcelProperties += value; } }
815 remove { lock (m_ParcelPropertiesLock) { m_ParcelProperties -= value; } }
816 }
817  
818 /// <summary>The event subscribers. null if no subcribers</summary>
819 private EventHandler<ParcelAccessListReplyEventArgs> m_ParcelACL;
820  
821 /// <summary>Raises the ParcelAccessListReply event</summary>
822 /// <param name="e">A ParcelAccessListReplyEventArgs object containing the
823 /// data returned from the simulator</param>
824 protected virtual void OnParcelAccessListReply(ParcelAccessListReplyEventArgs e)
825 {
826 EventHandler<ParcelAccessListReplyEventArgs> handler = m_ParcelACL;
827 if (handler != null)
828 handler(this, e);
829 }
830  
831 /// <summary>Thread sync lock object</summary>
832 private readonly object m_ParcelACLLock = new object();
833  
834 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelAccessList"/> request</summary>
835 public event EventHandler<ParcelAccessListReplyEventArgs> ParcelAccessListReply
836 {
837 add { lock (m_ParcelACLLock) { m_ParcelACL += value; } }
838 remove { lock (m_ParcelACLLock) { m_ParcelACL -= value; } }
839 }
840  
841 /// <summary>The event subscribers. null if no subcribers</summary>
842 private EventHandler<ParcelObjectOwnersReplyEventArgs> m_ParcelObjectOwnersReply;
843  
844 /// <summary>Raises the ParcelObjectOwnersReply event</summary>
845 /// <param name="e">A ParcelObjectOwnersReplyEventArgs object containing the
846 /// data returned from the simulator</param>
847 protected virtual void OnParcelObjectOwnersReply(ParcelObjectOwnersReplyEventArgs e)
848 {
849 EventHandler<ParcelObjectOwnersReplyEventArgs> handler = m_ParcelObjectOwnersReply;
850 if (handler != null)
851 handler(this, e);
852 }
853  
854 /// <summary>Thread sync lock object</summary>
855 private readonly object m_ParcelObjectOwnersLock = new object();
856  
857 /// <summary>Raised when the simulator responds to a <see cref="RequestObjectOwners"/> request</summary>
858 public event EventHandler<ParcelObjectOwnersReplyEventArgs> ParcelObjectOwnersReply
859 {
860 add { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply += value; } }
861 remove { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply -= value; } }
862 }
863  
864 /// <summary>The event subscribers. null if no subcribers</summary>
865 private EventHandler<SimParcelsDownloadedEventArgs> m_SimParcelsDownloaded;
866  
867 /// <summary>Raises the SimParcelsDownloaded event</summary>
868 /// <param name="e">A SimParcelsDownloadedEventArgs object containing the
869 /// data returned from the simulator</param>
870 protected virtual void OnSimParcelsDownloaded(SimParcelsDownloadedEventArgs e)
871 {
872 EventHandler<SimParcelsDownloadedEventArgs> handler = m_SimParcelsDownloaded;
873 if (handler != null)
874 handler(this, e);
875 }
876  
877 /// <summary>Thread sync lock object</summary>
878 private readonly object m_SimParcelsDownloadedLock = new object();
879  
880 /// <summary>Raised when the simulator responds to a <see cref="RequestAllSimParcels"/> request</summary>
881 public event EventHandler<SimParcelsDownloadedEventArgs> SimParcelsDownloaded
882 {
883 add { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded += value; } }
884 remove { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded -= value; } }
885 }
886  
887 /// <summary>The event subscribers. null if no subcribers</summary>
888 private EventHandler<ForceSelectObjectsReplyEventArgs> m_ForceSelectObjects;
889  
890 /// <summary>Raises the ForceSelectObjectsReply event</summary>
891 /// <param name="e">A ForceSelectObjectsReplyEventArgs object containing the
892 /// data returned from the simulator</param>
893 protected virtual void OnForceSelectObjectsReply(ForceSelectObjectsReplyEventArgs e)
894 {
895 EventHandler<ForceSelectObjectsReplyEventArgs> handler = m_ForceSelectObjects;
896 if (handler != null)
897 handler(this, e);
898 }
899  
900 /// <summary>Thread sync lock object</summary>
901 private readonly object m_ForceSelectObjectsLock = new object();
902  
903 /// <summary>Raised when the simulator responds to a <see cref="RequestForceSelectObjects"/> request</summary>
904 public event EventHandler<ForceSelectObjectsReplyEventArgs> ForceSelectObjectsReply
905 {
906 add { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects += value; } }
907 remove { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects -= value; } }
908 }
909  
910 /// <summary>The event subscribers. null if no subcribers</summary>
911 private EventHandler<ParcelMediaUpdateReplyEventArgs> m_ParcelMediaUpdateReply;
912  
913 /// <summary>Raises the ParcelMediaUpdateReply event</summary>
914 /// <param name="e">A ParcelMediaUpdateReplyEventArgs object containing the
915 /// data returned from the simulator</param>
916 protected virtual void OnParcelMediaUpdateReply(ParcelMediaUpdateReplyEventArgs e)
917 {
918 EventHandler<ParcelMediaUpdateReplyEventArgs> handler = m_ParcelMediaUpdateReply;
919 if (handler != null)
920 handler(this, e);
921 }
922  
923 /// <summary>Thread sync lock object</summary>
924 private readonly object m_ParcelMediaUpdateReplyLock = new object();
925  
926 /// <summary>Raised when the simulator responds to a Parcel Update request</summary>
927 public event EventHandler<ParcelMediaUpdateReplyEventArgs> ParcelMediaUpdateReply
928 {
929 add { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply += value; } }
930 remove { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply -= value; } }
931 }
932  
933 /// <summary>The event subscribers. null if no subcribers</summary>
934 private EventHandler<ParcelMediaCommandEventArgs> m_ParcelMediaCommand;
935  
936 /// <summary>Raises the ParcelMediaCommand event</summary>
937 /// <param name="e">A ParcelMediaCommandEventArgs object containing the
938 /// data returned from the simulator</param>
939 protected virtual void OnParcelMediaCommand(ParcelMediaCommandEventArgs e)
940 {
941 EventHandler<ParcelMediaCommandEventArgs> handler = m_ParcelMediaCommand;
942 if (handler != null)
943 handler(this, e);
944 }
945  
946 /// <summary>Thread sync lock object</summary>
947 private readonly object m_ParcelMediaCommandLock = new object();
948  
949 /// <summary>Raised when the parcel your agent is located sends a ParcelMediaCommand</summary>
950 public event EventHandler<ParcelMediaCommandEventArgs> ParcelMediaCommand
951 {
952 add { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand += value; } }
953 remove { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand -= value; } }
954 }
955 #endregion Delegates
956  
957 private GridClient Client;
958 private AutoResetEvent WaitForSimParcel;
959  
960 #region Public Methods
961  
962 /// <summary>
963 /// Default constructor
964 /// </summary>
965 /// <param name="client">A reference to the GridClient object</param>
966 public ParcelManager(GridClient client)
967 {
968 Client = client;
969  
970 // Setup the callbacks
971 Client.Network.RegisterCallback(PacketType.ParcelInfoReply, ParcelInfoReplyHandler);
972 Client.Network.RegisterEventCallback("ParcelObjectOwnersReply", new Caps.EventQueueCallback(ParcelObjectOwnersReplyHandler));
973 // CAPS packet handler, to allow for Media Data not contained in the message template
974 Client.Network.RegisterEventCallback("ParcelProperties", new Caps.EventQueueCallback(ParcelPropertiesReplyHandler));
975 Client.Network.RegisterCallback(PacketType.ParcelDwellReply, ParcelDwellReplyHandler);
976 Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, ParcelAccessListReplyHandler);
977 Client.Network.RegisterCallback(PacketType.ForceObjectSelect, SelectParcelObjectsReplyHandler);
978 Client.Network.RegisterCallback(PacketType.ParcelMediaUpdate, ParcelMediaUpdateHandler);
979 Client.Network.RegisterCallback(PacketType.ParcelOverlay, ParcelOverlayHandler);
980 Client.Network.RegisterCallback(PacketType.ParcelMediaCommandMessage, ParcelMediaCommandMessagePacketHandler);
981 }
982  
983 /// <summary>
984 /// Request basic information for a single parcel
985 /// </summary>
986 /// <param name="parcelID">Simulator-local ID of the parcel</param>
987 public void RequestParcelInfo(UUID parcelID)
988 {
989 ParcelInfoRequestPacket request = new ParcelInfoRequestPacket();
990 request.AgentData.AgentID = Client.Self.AgentID;
991 request.AgentData.SessionID = Client.Self.SessionID;
992 request.Data.ParcelID = parcelID;
993  
994 Client.Network.SendPacket(request);
995 }
996  
997 /// <summary>
998 /// Request properties of a single parcel
999 /// </summary>
1000 /// <param name="simulator">Simulator containing the parcel</param>
1001 /// <param name="localID">Simulator-local ID of the parcel</param>
1002 /// <param name="sequenceID">An arbitrary integer that will be returned
1003 /// with the ParcelProperties reply, useful for distinguishing between
1004 /// multiple simultaneous requests</param>
1005 public void RequestParcelProperties(Simulator simulator, int localID, int sequenceID)
1006 {
1007 ParcelPropertiesRequestByIDPacket request = new ParcelPropertiesRequestByIDPacket();
1008  
1009 request.AgentData.AgentID = Client.Self.AgentID;
1010 request.AgentData.SessionID = Client.Self.SessionID;
1011  
1012 request.ParcelData.LocalID = localID;
1013 request.ParcelData.SequenceID = sequenceID;
1014  
1015 Client.Network.SendPacket(request, simulator);
1016 }
1017  
1018 /// <summary>
1019 /// Request the access list for a single parcel
1020 /// </summary>
1021 /// <param name="simulator">Simulator containing the parcel</param>
1022 /// <param name="localID">Simulator-local ID of the parcel</param>
1023 /// <param name="sequenceID">An arbitrary integer that will be returned
1024 /// with the ParcelAccessList reply, useful for distinguishing between
1025 /// multiple simultaneous requests</param>
1026 /// <param name="flags"></param>
1027 public void RequestParcelAccessList(Simulator simulator, int localID, AccessList flags, int sequenceID)
1028 {
1029 ParcelAccessListRequestPacket request = new ParcelAccessListRequestPacket();
1030  
1031 request.AgentData.AgentID = Client.Self.AgentID;
1032 request.AgentData.SessionID = Client.Self.SessionID;
1033 request.Data.LocalID = localID;
1034 request.Data.Flags = (uint)flags;
1035 request.Data.SequenceID = sequenceID;
1036  
1037 Client.Network.SendPacket(request, simulator);
1038 }
1039  
1040 /// <summary>
1041 /// Request properties of parcels using a bounding box selection
1042 /// </summary>
1043 /// <param name="simulator">Simulator containing the parcel</param>
1044 /// <param name="north">Northern boundary of the parcel selection</param>
1045 /// <param name="east">Eastern boundary of the parcel selection</param>
1046 /// <param name="south">Southern boundary of the parcel selection</param>
1047 /// <param name="west">Western boundary of the parcel selection</param>
1048 /// <param name="sequenceID">An arbitrary integer that will be returned
1049 /// with the ParcelProperties reply, useful for distinguishing between
1050 /// different types of parcel property requests</param>
1051 /// <param name="snapSelection">A boolean that is returned with the
1052 /// ParcelProperties reply, useful for snapping focus to a single
1053 /// parcel</param>
1054 public void RequestParcelProperties(Simulator simulator, float north, float east, float south, float west,
1055 int sequenceID, bool snapSelection)
1056 {
1057 ParcelPropertiesRequestPacket request = new ParcelPropertiesRequestPacket();
1058  
1059 request.AgentData.AgentID = Client.Self.AgentID;
1060 request.AgentData.SessionID = Client.Self.SessionID;
1061 request.ParcelData.North = north;
1062 request.ParcelData.East = east;
1063 request.ParcelData.South = south;
1064 request.ParcelData.West = west;
1065 request.ParcelData.SequenceID = sequenceID;
1066 request.ParcelData.SnapSelection = snapSelection;
1067  
1068 Client.Network.SendPacket(request, simulator);
1069 }
1070  
1071 /// <summary>
1072 /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
1073 /// dictionary)
1074 /// </summary>
1075 /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
1076 public void RequestAllSimParcels(Simulator simulator)
1077 {
1078 RequestAllSimParcels(simulator, false, 750);
1079 }
1080  
1081 /// <summary>
1082 /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
1083 /// dictionary)
1084 /// </summary>
1085 /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
1086 /// <param name="refresh">If TRUE, will force a full refresh</param>
1087 /// <param name="msDelay">Number of milliseconds to pause in between each request</param>
1088 public void RequestAllSimParcels(Simulator simulator, bool refresh, int msDelay)
1089 {
1090 if (simulator.DownloadingParcelMap)
1091 {
1092 Logger.Log("Already downloading parcels in " + simulator.Name, Helpers.LogLevel.Info, Client);
1093 return;
1094 }
1095 else
1096 {
1097 simulator.DownloadingParcelMap = true;
1098 WaitForSimParcel = new AutoResetEvent(false);
1099 }
1100  
1101 if (refresh)
1102 {
1103 for (int y = 0; y < 64; y++)
1104 for (int x = 0; x < 64; x++)
1105 simulator.ParcelMap[y, x] = 0;
1106 }
1107  
1108 Thread th = new Thread(delegate()
1109 {
1110 int count = 0, timeouts = 0, y, x;
1111  
1112 for (y = 0; y < 64; y++)
1113 {
1114 for (x = 0; x < 64; x++)
1115 {
1116 if (!Client.Network.Connected)
1117 return;
1118  
1119 if (simulator.ParcelMap[y, x] == 0)
1120 {
1121 Client.Parcels.RequestParcelProperties(simulator,
1122 (y + 1) * 4.0f, (x + 1) * 4.0f,
1123 y * 4.0f, x * 4.0f, int.MaxValue, false);
1124  
1125 // Wait the given amount of time for a reply before sending the next request
1126 if (!WaitForSimParcel.WaitOne(msDelay, false))
1127 ++timeouts;
1128  
1129 ++count;
1130 }
1131 }
1132 }
1133  
1134 Logger.Log(String.Format(
1135 "Full simulator parcel information retrieved. Sent {0} parcel requests. Current outgoing queue: {1}, Retry Count {2}",
1136 count, Client.Network.OutboxCount, timeouts), Helpers.LogLevel.Info, Client);
1137  
1138 simulator.DownloadingParcelMap = false;
1139 });
1140  
1141 th.Start();
1142 }
1143  
1144 /// <summary>
1145 /// Request the dwell value for a parcel
1146 /// </summary>
1147 /// <param name="simulator">Simulator containing the parcel</param>
1148 /// <param name="localID">Simulator-local ID of the parcel</param>
1149 public void RequestDwell(Simulator simulator, int localID)
1150 {
1151 ParcelDwellRequestPacket request = new ParcelDwellRequestPacket();
1152 request.AgentData.AgentID = Client.Self.AgentID;
1153 request.AgentData.SessionID = Client.Self.SessionID;
1154 request.Data.LocalID = localID;
1155 request.Data.ParcelID = UUID.Zero; // Not used by clients
1156  
1157 Client.Network.SendPacket(request, simulator);
1158 }
1159  
1160 /// <summary>
1161 /// Send a request to Purchase a parcel of land
1162 /// </summary>
1163 /// <param name="simulator">The Simulator the parcel is located in</param>
1164 /// <param name="localID">The parcels region specific local ID</param>
1165 /// <param name="forGroup">true if this parcel is being purchased by a group</param>
1166 /// <param name="groupID">The groups <seealso cref="T:OpenMetaverse.UUID"/></param>
1167 /// <param name="removeContribution">true to remove tier contribution if purchase is successful</param>
1168 /// <param name="parcelArea">The parcels size</param>
1169 /// <param name="parcelPrice">The purchase price of the parcel</param>
1170 /// <returns></returns>
1171 public void Buy(Simulator simulator, int localID, bool forGroup, UUID groupID,
1172 bool removeContribution, int parcelArea, int parcelPrice)
1173 {
1174 ParcelBuyPacket request = new ParcelBuyPacket();
1175  
1176 request.AgentData.AgentID = Client.Self.AgentID;
1177 request.AgentData.SessionID = Client.Self.SessionID;
1178  
1179 request.Data.Final = true;
1180 request.Data.GroupID = groupID;
1181 request.Data.LocalID = localID;
1182 request.Data.IsGroupOwned = forGroup;
1183 request.Data.RemoveContribution = removeContribution;
1184  
1185 request.ParcelData.Area = parcelArea;
1186 request.ParcelData.Price = parcelPrice;
1187  
1188 Client.Network.SendPacket(request, simulator);
1189 }
1190  
1191 /// <summary>
1192 /// Reclaim a parcel of land
1193 /// </summary>
1194 /// <param name="simulator">The simulator the parcel is in</param>
1195 /// <param name="localID">The parcels region specific local ID</param>
1196 public void Reclaim(Simulator simulator, int localID)
1197 {
1198 ParcelReclaimPacket request = new ParcelReclaimPacket();
1199 request.AgentData.AgentID = Client.Self.AgentID;
1200 request.AgentData.SessionID = Client.Self.SessionID;
1201  
1202 request.Data.LocalID = localID;
1203  
1204 Client.Network.SendPacket(request, simulator);
1205 }
1206  
1207 /// <summary>
1208 /// Deed a parcel to a group
1209 /// </summary>
1210 /// <param name="simulator">The simulator the parcel is in</param>
1211 /// <param name="localID">The parcels region specific local ID</param>
1212 /// <param name="groupID">The groups <seealso cref="T:OpenMetaverse.UUID"/></param>
1213 public void DeedToGroup(Simulator simulator, int localID, UUID groupID)
1214 {
1215 ParcelDeedToGroupPacket request = new ParcelDeedToGroupPacket();
1216 request.AgentData.AgentID = Client.Self.AgentID;
1217 request.AgentData.SessionID = Client.Self.SessionID;
1218  
1219 request.Data.LocalID = localID;
1220 request.Data.GroupID = groupID;
1221  
1222 Client.Network.SendPacket(request, simulator);
1223 }
1224  
1225 /// <summary>
1226 /// Request prim owners of a parcel of land.
1227 /// </summary>
1228 /// <param name="simulator">Simulator parcel is in</param>
1229 /// <param name="localID">The parcels region specific local ID</param>
1230 public void RequestObjectOwners(Simulator simulator, int localID)
1231 {
1232 ParcelObjectOwnersRequestPacket request = new ParcelObjectOwnersRequestPacket();
1233  
1234 request.AgentData.AgentID = Client.Self.AgentID;
1235 request.AgentData.SessionID = Client.Self.SessionID;
1236  
1237 request.ParcelData.LocalID = localID;
1238 Client.Network.SendPacket(request, simulator);
1239 }
1240  
1241 /// <summary>
1242 /// Return objects from a parcel
1243 /// </summary>
1244 /// <param name="simulator">Simulator parcel is in</param>
1245 /// <param name="localID">The parcels region specific local ID</param>
1246 /// <param name="type">the type of objects to return, <seealso cref="T:OpenMetaverse.ObjectReturnType"/></param>
1247 /// <param name="ownerIDs">A list containing object owners <seealso cref="OpenMetaverse.UUID"/>s to return</param>
1248 public void ReturnObjects(Simulator simulator, int localID, ObjectReturnType type, List<UUID> ownerIDs)
1249 {
1250 ParcelReturnObjectsPacket request = new ParcelReturnObjectsPacket();
1251 request.AgentData.AgentID = Client.Self.AgentID;
1252 request.AgentData.SessionID = Client.Self.SessionID;
1253  
1254 request.ParcelData.LocalID = localID;
1255 request.ParcelData.ReturnType = (uint)type;
1256  
1257 // A single null TaskID is (not) used for parcel object returns
1258 request.TaskIDs = new ParcelReturnObjectsPacket.TaskIDsBlock[1];
1259 request.TaskIDs[0] = new ParcelReturnObjectsPacket.TaskIDsBlock();
1260 request.TaskIDs[0].TaskID = UUID.Zero;
1261  
1262 // Convert the list of owner UUIDs to packet blocks if a list is given
1263 if (ownerIDs != null)
1264 {
1265 request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[ownerIDs.Count];
1266  
1267 for (int i = 0; i < ownerIDs.Count; i++)
1268 {
1269 request.OwnerIDs[i] = new ParcelReturnObjectsPacket.OwnerIDsBlock();
1270 request.OwnerIDs[i].OwnerID = ownerIDs[i];
1271 }
1272 }
1273 else
1274 {
1275 request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[0];
1276 }
1277  
1278 Client.Network.SendPacket(request, simulator);
1279 }
1280  
1281 /// <summary>
1282 /// Subdivide (split) a parcel
1283 /// </summary>
1284 /// <param name="simulator"></param>
1285 /// <param name="west"></param>
1286 /// <param name="south"></param>
1287 /// <param name="east"></param>
1288 /// <param name="north"></param>
1289 public void ParcelSubdivide(Simulator simulator, float west, float south, float east, float north)
1290 {
1291 ParcelDividePacket divide = new ParcelDividePacket();
1292 divide.AgentData.AgentID = Client.Self.AgentID;
1293 divide.AgentData.SessionID = Client.Self.SessionID;
1294 divide.ParcelData.East = east;
1295 divide.ParcelData.North = north;
1296 divide.ParcelData.South = south;
1297 divide.ParcelData.West = west;
1298  
1299 Client.Network.SendPacket(divide, simulator);
1300 }
1301  
1302 /// <summary>
1303 /// Join two parcels of land creating a single parcel
1304 /// </summary>
1305 /// <param name="simulator"></param>
1306 /// <param name="west"></param>
1307 /// <param name="south"></param>
1308 /// <param name="east"></param>
1309 /// <param name="north"></param>
1310 public void ParcelJoin(Simulator simulator, float west, float south, float east, float north)
1311 {
1312 ParcelJoinPacket join = new ParcelJoinPacket();
1313 join.AgentData.AgentID = Client.Self.AgentID;
1314 join.AgentData.SessionID = Client.Self.SessionID;
1315 join.ParcelData.East = east;
1316 join.ParcelData.North = north;
1317 join.ParcelData.South = south;
1318 join.ParcelData.West = west;
1319  
1320 Client.Network.SendPacket(join, simulator);
1321 }
1322  
1323 /// <summary>
1324 /// Get a parcels LocalID
1325 /// </summary>
1326 /// <param name="simulator">Simulator parcel is in</param>
1327 /// <param name="position">Vector3 position in simulator (Z not used)</param>
1328 /// <returns>0 on failure, or parcel LocalID on success.</returns>
1329 /// <remarks>A call to <code>Parcels.RequestAllSimParcels</code> is required to populate map and
1330 /// dictionary.</remarks>
1331 public int GetParcelLocalID(Simulator simulator, Vector3 position)
1332 {
1333 if (simulator.ParcelMap[(byte)position.Y / 4, (byte)position.X / 4] > 0)
1334 {
1335 return simulator.ParcelMap[(byte)position.Y / 4, (byte)position.X / 4];
1336 }
1337 else
1338 {
1339 Logger.Log(String.Format("ParcelMap returned an default/invalid value for location {0}/{1} Did you use RequestAllSimParcels() to populate the dictionaries?", (byte)position.Y / 4, (byte)position.X / 4 ), Helpers.LogLevel.Warning);
1340 return 0;
1341 }
1342 }
1343  
1344 /// <summary>
1345 /// Terraform (raise, lower, etc) an area or whole parcel of land
1346 /// </summary>
1347 /// <param name="simulator">Simulator land area is in.</param>
1348 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1349 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1350 /// <param name="brushSize">Size of area to modify</param>
1351 /// <returns>true on successful request sent.</returns>
1352 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1353 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1354 public bool Terraform(Simulator simulator, int localID, TerraformAction action, TerraformBrushSize brushSize)
1355 {
1356 return Terraform(simulator, localID, 0f, 0f, 0f, 0f, action, brushSize, 1);
1357 }
1358  
1359 /// <summary>
1360 /// Terraform (raise, lower, etc) an area or whole parcel of land
1361 /// </summary>
1362 /// <param name="simulator">Simulator land area is in.</param>
1363 /// <param name="west">west border of area to modify</param>
1364 /// <param name="south">south border of area to modify</param>
1365 /// <param name="east">east border of area to modify</param>
1366 /// <param name="north">north border of area to modify</param>
1367 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1368 /// <param name="brushSize">Size of area to modify</param>
1369 /// <returns>true on successful request sent.</returns>
1370 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1371 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1372 public bool Terraform(Simulator simulator, float west, float south, float east, float north,
1373 TerraformAction action, TerraformBrushSize brushSize)
1374 {
1375 return Terraform(simulator, -1, west, south, east, north, action, brushSize, 1);
1376 }
1377  
1378 /// <summary>
1379 /// Terraform (raise, lower, etc) an area or whole parcel of land
1380 /// </summary>
1381 /// <param name="simulator">Simulator land area is in.</param>
1382 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1383 /// <param name="west">west border of area to modify</param>
1384 /// <param name="south">south border of area to modify</param>
1385 /// <param name="east">east border of area to modify</param>
1386 /// <param name="north">north border of area to modify</param>
1387 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1388 /// <param name="brushSize">Size of area to modify</param>
1389 /// <param name="seconds">How many meters + or - to lower, 1 = 1 meter</param>
1390 /// <returns>true on successful request sent.</returns>
1391 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1392 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1393 public bool Terraform(Simulator simulator, int localID, float west, float south, float east, float north,
1394 TerraformAction action, TerraformBrushSize brushSize, int seconds)
1395 {
1396 float height = 0f;
1397 int x, y;
1398 if (localID == -1)
1399 {
1400 x = (int)east - (int)west / 2;
1401 y = (int)north - (int)south / 2;
1402 }
1403 else
1404 {
1405 Parcel p;
1406 if (!simulator.Parcels.TryGetValue(localID, out p))
1407 {
1408 Logger.Log(String.Format("Can't find parcel {0} in simulator {1}", localID, simulator),
1409 Helpers.LogLevel.Warning, Client);
1410 return false;
1411 }
1412  
1413 x = (int)p.AABBMax.X - (int)p.AABBMin.X / 2;
1414 y = (int)p.AABBMax.Y - (int)p.AABBMin.Y / 2;
1415 }
1416  
1417 if (!simulator.TerrainHeightAtPoint(x, y, out height))
1418 {
1419 Logger.Log("Land Patch not stored for location", Helpers.LogLevel.Warning, Client);
1420 return false;
1421 }
1422  
1423 Terraform(simulator, localID, west, south, east, north, action, brushSize, seconds, height);
1424 return true;
1425 }
1426  
1427 /// <summary>
1428 /// Terraform (raise, lower, etc) an area or whole parcel of land
1429 /// </summary>
1430 /// <param name="simulator">Simulator land area is in.</param>
1431 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1432 /// <param name="west">west border of area to modify</param>
1433 /// <param name="south">south border of area to modify</param>
1434 /// <param name="east">east border of area to modify</param>
1435 /// <param name="north">north border of area to modify</param>
1436 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1437 /// <param name="brushSize">Size of area to modify</param>
1438 /// <param name="seconds">How many meters + or - to lower, 1 = 1 meter</param>
1439 /// <param name="height">Height at which the terraform operation is acting at</param>
1440 public void Terraform(Simulator simulator, int localID, float west, float south, float east, float north,
1441 TerraformAction action, TerraformBrushSize brushSize, int seconds, float height)
1442 {
1443 ModifyLandPacket land = new ModifyLandPacket();
1444 land.AgentData.AgentID = Client.Self.AgentID;
1445 land.AgentData.SessionID = Client.Self.SessionID;
1446  
1447 land.ModifyBlock.Action = (byte)action;
1448 land.ModifyBlock.BrushSize = (byte)brushSize;
1449 land.ModifyBlock.Seconds = seconds;
1450 land.ModifyBlock.Height = height;
1451  
1452 land.ParcelData = new ModifyLandPacket.ParcelDataBlock[1];
1453 land.ParcelData[0] = new ModifyLandPacket.ParcelDataBlock();
1454 land.ParcelData[0].LocalID = localID;
1455 land.ParcelData[0].West = west;
1456 land.ParcelData[0].South = south;
1457 land.ParcelData[0].East = east;
1458 land.ParcelData[0].North = north;
1459  
1460 land.ModifyBlockExtended = new ModifyLandPacket.ModifyBlockExtendedBlock[1];
1461 land.ModifyBlockExtended[0] = new ModifyLandPacket.ModifyBlockExtendedBlock();
1462 land.ModifyBlockExtended[0].BrushSize = (float)brushSize;
1463  
1464 Client.Network.SendPacket(land, simulator);
1465 }
1466  
1467 /// <summary>
1468 /// Sends a request to the simulator to return a list of objects owned by specific owners
1469 /// </summary>
1470 /// <param name="localID">Simulator local ID of parcel</param>
1471 /// <param name="selectType">Owners, Others, Etc</param>
1472 /// <param name="ownerID">List containing keys of avatars objects to select;
1473 /// if List is null will return Objects of type <c>selectType</c></param>
1474 /// <remarks>Response data is returned in the event <seealso cref="E:ForceSelectObjectsReply"/></remarks>
1475 public void RequestSelectObjects(int localID, ObjectReturnType selectType, UUID ownerID)
1476 {
1477 ParcelSelectObjectsPacket select = new ParcelSelectObjectsPacket();
1478 select.AgentData.AgentID = Client.Self.AgentID;
1479 select.AgentData.SessionID = Client.Self.SessionID;
1480  
1481 select.ParcelData.LocalID = localID;
1482 select.ParcelData.ReturnType = (uint)selectType;
1483  
1484 select.ReturnIDs = new ParcelSelectObjectsPacket.ReturnIDsBlock[1];
1485 select.ReturnIDs[0] = new ParcelSelectObjectsPacket.ReturnIDsBlock();
1486 select.ReturnIDs[0].ReturnID = ownerID;
1487  
1488 Client.Network.SendPacket(select);
1489 }
1490  
1491 /// <summary>
1492 /// Eject and optionally ban a user from a parcel
1493 /// </summary>
1494 /// <param name="targetID">target key of avatar to eject</param>
1495 /// <param name="ban">true to also ban target</param>
1496 public void EjectUser(UUID targetID, bool ban)
1497 {
1498 EjectUserPacket eject = new EjectUserPacket();
1499 eject.AgentData.AgentID = Client.Self.AgentID;
1500 eject.AgentData.SessionID = Client.Self.SessionID;
1501 eject.Data.TargetID = targetID;
1502 if (ban) eject.Data.Flags = 1;
1503 else eject.Data.Flags = 0;
1504  
1505 Client.Network.SendPacket(eject);
1506 }
1507  
1508 /// <summary>
1509 /// Freeze or unfreeze an avatar over your land
1510 /// </summary>
1511 /// <param name="targetID">target key to freeze</param>
1512 /// <param name="freeze">true to freeze, false to unfreeze</param>
1513 public void FreezeUser(UUID targetID, bool freeze)
1514 {
1515 FreezeUserPacket frz = new FreezeUserPacket();
1516 frz.AgentData.AgentID = Client.Self.AgentID;
1517 frz.AgentData.SessionID = Client.Self.SessionID;
1518 frz.Data.TargetID = targetID;
1519 if (freeze) frz.Data.Flags = 0;
1520 else frz.Data.Flags = 1;
1521  
1522 Client.Network.SendPacket(frz);
1523 }
1524  
1525 /// <summary>
1526 /// Abandon a parcel of land
1527 /// </summary>
1528 /// <param name="simulator">Simulator parcel is in</param>
1529 /// <param name="localID">Simulator local ID of parcel</param>
1530 public void ReleaseParcel(Simulator simulator, int localID)
1531 {
1532 ParcelReleasePacket abandon = new ParcelReleasePacket();
1533 abandon.AgentData.AgentID = Client.Self.AgentID;
1534 abandon.AgentData.SessionID = Client.Self.SessionID;
1535 abandon.Data.LocalID = localID;
1536  
1537 Client.Network.SendPacket(abandon, simulator);
1538 }
1539  
1540 /// <summary>
1541 /// Requests the UUID of the parcel in a remote region at a specified location
1542 /// </summary>
1543 /// <param name="location">Location of the parcel in the remote region</param>
1544 /// <param name="regionHandle">Remote region handle</param>
1545 /// <param name="regionID">Remote region UUID</param>
1546 /// <returns>If successful UUID of the remote parcel, UUID.Zero otherwise</returns>
1547 public UUID RequestRemoteParcelID(Vector3 location, ulong regionHandle, UUID regionID)
1548 {
1549 if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null)
1550 return UUID.Zero;
1551  
1552 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("RemoteParcelRequest");
1553  
1554 if (url != null)
1555 {
1556 RemoteParcelRequestRequest msg = new RemoteParcelRequestRequest();
1557 msg.Location = location;
1558 msg.RegionHandle = regionHandle;
1559 msg.RegionID = regionID;
1560  
1561 try
1562 {
1563 CapsClient request = new CapsClient(url);
1564 OSD result = request.GetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1565 RemoteParcelRequestReply response = new RemoteParcelRequestReply();
1566 response.Deserialize((OSDMap)result);
1567 return response.ParcelID;
1568 }
1569 catch (Exception)
1570 {
1571 Logger.Log("Failed to fetch remote parcel ID", Helpers.LogLevel.Debug, Client);
1572 }
1573 }
1574  
1575 return UUID.Zero;
1576  
1577 }
1578  
1579 /// <summary>
1580 /// Retrieves information on resources used by the parcel
1581 /// </summary>
1582 /// <param name="parcelID">UUID of the parcel</param>
1583 /// <param name="getDetails">Should per object resource usage be requested</param>
1584 /// <param name="callback">Callback invoked when the request is complete</param>
1585 public void GetParcelResouces(UUID parcelID, bool getDetails, LandResourcesCallback callback)
1586 {
1587 try
1588 {
1589 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("LandResources");
1590 CapsClient request = new CapsClient(url);
1591  
1592 request.OnComplete += delegate(CapsClient client, OSD result, Exception error)
1593 {
1594 try
1595 {
1596 if (result == null || error != null)
1597 {
1598 callback(false, null);
1599 }
1600 LandResourcesMessage response = new LandResourcesMessage();
1601 response.Deserialize((OSDMap)result);
1602  
1603 CapsClient summaryRequest = new CapsClient(response.ScriptResourceSummary);
1604 OSD summaryResponse = summaryRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
1605  
1606 LandResourcesInfo res = new LandResourcesInfo();
1607 res.Deserialize((OSDMap)summaryResponse);
1608  
1609 if (response.ScriptResourceDetails != null && getDetails)
1610 {
1611 CapsClient detailRequest = new CapsClient(response.ScriptResourceDetails);
1612 OSD detailResponse = detailRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
1613 res.Deserialize((OSDMap)detailResponse);
1614 }
1615 callback(true, res);
1616 }
1617 catch (Exception ex)
1618 {
1619 Logger.Log("Failed fetching land resources", Helpers.LogLevel.Error, Client, ex);
1620 callback(false, null);
1621 }
1622 };
1623  
1624 LandResourcesRequest param = new LandResourcesRequest();
1625 param.ParcelID = parcelID;
1626 request.BeginGetResponse(param.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1627  
1628 }
1629 catch (Exception ex)
1630 {
1631 Logger.Log("Failed fetching land resources:", Helpers.LogLevel.Error, Client, ex);
1632 callback(false, null);
1633 }
1634 }
1635  
1636 #endregion Public Methods
1637  
1638 #region Packet Handlers
1639  
1640 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1641 /// <param name="sender">The sender</param>
1642 /// <param name="e">The EventArgs object containing the packet data</param>
1643 /// <remarks>Raises the <see cref="ParcelDwellReply"/> event</remarks>
1644 protected void ParcelDwellReplyHandler(object sender, PacketReceivedEventArgs e)
1645 {
1646 if (m_DwellReply != null || Client.Settings.ALWAYS_REQUEST_PARCEL_DWELL == true)
1647 {
1648 Packet packet = e.Packet;
1649 Simulator simulator = e.Simulator;
1650  
1651 ParcelDwellReplyPacket dwell = (ParcelDwellReplyPacket)packet;
1652  
1653 lock (simulator.Parcels.Dictionary)
1654 {
1655 if (simulator.Parcels.Dictionary.ContainsKey(dwell.Data.LocalID))
1656 {
1657 Parcel parcel = simulator.Parcels.Dictionary[dwell.Data.LocalID];
1658 parcel.Dwell = dwell.Data.Dwell;
1659 simulator.Parcels.Dictionary[dwell.Data.LocalID] = parcel;
1660 }
1661 }
1662  
1663 if (m_DwellReply != null)
1664 {
1665 OnParcelDwellReply(new ParcelDwellReplyEventArgs(dwell.Data.ParcelID, dwell.Data.LocalID, dwell.Data.Dwell));
1666 }
1667 }
1668 }
1669  
1670 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1671 /// <param name="sender">The sender</param>
1672 /// <param name="e">The EventArgs object containing the packet data</param>
1673 /// <remarks>Raises the <see cref="ParcelInfoReply"/> event</remarks>
1674 protected void ParcelInfoReplyHandler(object sender, PacketReceivedEventArgs e)
1675 {
1676 if (m_ParcelInfo != null)
1677 {
1678 Packet packet = e.Packet;
1679 ParcelInfoReplyPacket info = (ParcelInfoReplyPacket)packet;
1680  
1681 ParcelInfo parcelInfo = new ParcelInfo();
1682  
1683 parcelInfo.ActualArea = info.Data.ActualArea;
1684 parcelInfo.AuctionID = info.Data.AuctionID;
1685 parcelInfo.BillableArea = info.Data.BillableArea;
1686 parcelInfo.Description = Utils.BytesToString(info.Data.Desc);
1687 parcelInfo.Dwell = info.Data.Dwell;
1688 parcelInfo.GlobalX = info.Data.GlobalX;
1689 parcelInfo.GlobalY = info.Data.GlobalY;
1690 parcelInfo.GlobalZ = info.Data.GlobalZ;
1691 parcelInfo.ID = info.Data.ParcelID;
1692 parcelInfo.Mature = ((info.Data.Flags & 1) != 0) ? true : false;
1693 parcelInfo.Name = Utils.BytesToString(info.Data.Name);
1694 parcelInfo.OwnerID = info.Data.OwnerID;
1695 parcelInfo.SalePrice = info.Data.SalePrice;
1696 parcelInfo.SimName = Utils.BytesToString(info.Data.SimName);
1697 parcelInfo.SnapshotID = info.Data.SnapshotID;
1698  
1699 OnParcelInfoReply(new ParcelInfoReplyEventArgs(parcelInfo));
1700 }
1701 }
1702  
1703 protected void ParcelPropertiesReplyHandler(string capsKey, IMessage message, Simulator simulator)
1704 {
1705 if (m_ParcelProperties != null || Client.Settings.PARCEL_TRACKING == true)
1706 {
1707 ParcelPropertiesMessage msg = (ParcelPropertiesMessage)message;
1708  
1709 Parcel parcel = new Parcel(msg.LocalID);
1710  
1711 parcel.AABBMax = msg.AABBMax;
1712 parcel.AABBMin = msg.AABBMin;
1713 parcel.Area = msg.Area;
1714 parcel.AuctionID = msg.AuctionID;
1715 parcel.AuthBuyerID = msg.AuthBuyerID;
1716 parcel.Bitmap = msg.Bitmap;
1717 parcel.Category = msg.Category;
1718 parcel.ClaimDate = msg.ClaimDate;
1719 parcel.ClaimPrice = msg.ClaimPrice;
1720 parcel.Desc = msg.Desc;
1721 parcel.Flags = msg.ParcelFlags;
1722 parcel.GroupID = msg.GroupID;
1723 parcel.GroupPrims = msg.GroupPrims;
1724 parcel.IsGroupOwned = msg.IsGroupOwned;
1725 parcel.Landing = msg.LandingType;
1726 parcel.MaxPrims = msg.MaxPrims;
1727 parcel.Media.MediaAutoScale = msg.MediaAutoScale;
1728 parcel.Media.MediaID = msg.MediaID;
1729 parcel.Media.MediaURL = msg.MediaURL;
1730 parcel.MusicURL = msg.MusicURL;
1731 parcel.Name = msg.Name;
1732 parcel.OtherCleanTime = msg.OtherCleanTime;
1733 parcel.OtherCount = msg.OtherCount;
1734 parcel.OtherPrims = msg.OtherPrims;
1735 parcel.OwnerID = msg.OwnerID;
1736 parcel.OwnerPrims = msg.OwnerPrims;
1737 parcel.ParcelPrimBonus = msg.ParcelPrimBonus;
1738 parcel.PassHours = msg.PassHours;
1739 parcel.PassPrice = msg.PassPrice;
1740 parcel.PublicCount = msg.PublicCount;
1741 parcel.RegionDenyAgeUnverified = msg.RegionDenyAgeUnverified;
1742 parcel.RegionDenyAnonymous = msg.RegionDenyAnonymous;
1743 parcel.RegionPushOverride = msg.RegionPushOverride;
1744 parcel.RentPrice = msg.RentPrice;
1745 ParcelResult result = msg.RequestResult;
1746 parcel.SalePrice = msg.SalePrice;
1747 int selectedPrims = msg.SelectedPrims;
1748 parcel.SelfCount = msg.SelfCount;
1749 int sequenceID = msg.SequenceID;
1750 parcel.SimWideMaxPrims = msg.SimWideMaxPrims;
1751 parcel.SimWideTotalPrims = msg.SimWideTotalPrims;
1752 bool snapSelection = msg.SnapSelection;
1753 parcel.SnapshotID = msg.SnapshotID;
1754 parcel.Status = msg.Status;
1755 parcel.TotalPrims = msg.TotalPrims;
1756 parcel.UserLocation = msg.UserLocation;
1757 parcel.UserLookAt = msg.UserLookAt;
1758 parcel.Media.MediaDesc = msg.MediaDesc;
1759 parcel.Media.MediaHeight = msg.MediaHeight;
1760 parcel.Media.MediaWidth = msg.MediaWidth;
1761 parcel.Media.MediaLoop = msg.MediaLoop;
1762 parcel.Media.MediaType = msg.MediaType;
1763 parcel.ObscureMedia = msg.ObscureMedia;
1764 parcel.ObscureMusic = msg.ObscureMusic;
1765  
1766 if (Client.Settings.PARCEL_TRACKING)
1767 {
1768 lock (simulator.Parcels.Dictionary)
1769 simulator.Parcels.Dictionary[parcel.LocalID] = parcel;
1770  
1771 bool set = false;
1772 int y, x, index, bit;
1773 for (y = 0; y < 64; y++)
1774 {
1775 for (x = 0; x < 64; x++)
1776 {
1777 index = (y * 64) + x;
1778 bit = index % 8;
1779 index >>= 3;
1780  
1781 if ((parcel.Bitmap[index] & (1 << bit)) != 0)
1782 {
1783 simulator.ParcelMap[y, x] = parcel.LocalID;
1784 set = true;
1785 }
1786 }
1787 }
1788  
1789 if (!set)
1790 {
1791 Logger.Log("Received a parcel with a bitmap that did not map to any locations",
1792 Helpers.LogLevel.Warning);
1793 }
1794 }
1795  
1796 if (sequenceID.Equals(int.MaxValue) && WaitForSimParcel != null)
1797 WaitForSimParcel.Set();
1798  
1799 // auto request acl, will be stored in parcel tracking dictionary if enabled
1800 if (Client.Settings.ALWAYS_REQUEST_PARCEL_ACL)
1801 Client.Parcels.RequestParcelAccessList(simulator, parcel.LocalID,
1802 AccessList.Both, sequenceID);
1803  
1804 // auto request dwell, will be stored in parcel tracking dictionary if enables
1805 if (Client.Settings.ALWAYS_REQUEST_PARCEL_DWELL)
1806 Client.Parcels.RequestDwell(simulator, parcel.LocalID);
1807  
1808 // Fire the callback for parcel properties being received
1809 if (m_ParcelProperties != null)
1810 {
1811 OnParcelProperties(new ParcelPropertiesEventArgs(simulator, parcel, result, selectedPrims, sequenceID, snapSelection));
1812 }
1813  
1814 // Check if all of the simulator parcels have been retrieved, if so fire another callback
1815 if (simulator.IsParcelMapFull() && m_SimParcelsDownloaded != null)
1816 {
1817 OnSimParcelsDownloaded(new SimParcelsDownloadedEventArgs(simulator, simulator.Parcels, simulator.ParcelMap));
1818 }
1819 }
1820 }
1821  
1822 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1823 /// <param name="sender">The sender</param>
1824 /// <param name="e">The EventArgs object containing the packet data</param>
1825 /// <remarks>Raises the <see cref="ParcelAccessListReply"/> event</remarks>
1826 protected void ParcelAccessListReplyHandler(object sender, PacketReceivedEventArgs e)
1827 {
1828 if (m_ParcelACL != null || Client.Settings.ALWAYS_REQUEST_PARCEL_ACL == true)
1829 {
1830 Packet packet = e.Packet;
1831 Simulator simulator = e.Simulator;
1832  
1833 ParcelAccessListReplyPacket reply = (ParcelAccessListReplyPacket)packet;
1834  
1835 List<ParcelAccessEntry> accessList = new List<ParcelAccessEntry>(reply.List.Length);
1836  
1837 for (int i = 0; i < reply.List.Length; i++)
1838 {
1839 ParcelAccessEntry pae = new ParcelAccessEntry();
1840 pae.AgentID = reply.List[i].ID;
1841 pae.Time = Utils.UnixTimeToDateTime((uint)reply.List[i].Time);
1842 pae.Flags = (AccessList)reply.List[i].Flags;
1843  
1844 accessList.Add(pae);
1845 }
1846  
1847 lock (simulator.Parcels.Dictionary)
1848 {
1849 if (simulator.Parcels.Dictionary.ContainsKey(reply.Data.LocalID))
1850 {
1851 Parcel parcel = simulator.Parcels.Dictionary[reply.Data.LocalID];
1852 if ((AccessList)reply.Data.Flags == AccessList.Ban)
1853 parcel.AccessBlackList = accessList;
1854 else
1855 parcel.AccessWhiteList = accessList;
1856  
1857 simulator.Parcels.Dictionary[reply.Data.LocalID] = parcel;
1858 }
1859 }
1860  
1861  
1862 if (m_ParcelACL != null)
1863 {
1864 OnParcelAccessListReply(new ParcelAccessListReplyEventArgs(simulator, reply.Data.SequenceID, reply.Data.LocalID,
1865 reply.Data.Flags, accessList));
1866 }
1867 }
1868 }
1869  
1870 protected void ParcelObjectOwnersReplyHandler(string capsKey, IMessage message, Simulator simulator)
1871 {
1872 if (m_ParcelObjectOwnersReply != null)
1873 {
1874 List<ParcelPrimOwners> primOwners = new List<ParcelPrimOwners>();
1875  
1876 ParcelObjectOwnersReplyMessage msg = (ParcelObjectOwnersReplyMessage)message;
1877  
1878 for (int i = 0; i < msg.PrimOwnersBlock.Length; i++)
1879 {
1880 ParcelPrimOwners primOwner = new ParcelPrimOwners();
1881 primOwner.OwnerID = msg.PrimOwnersBlock[i].OwnerID;
1882 primOwner.Count = msg.PrimOwnersBlock[i].Count;
1883 primOwner.IsGroupOwned = msg.PrimOwnersBlock[i].IsGroupOwned;
1884 primOwner.OnlineStatus = msg.PrimOwnersBlock[i].OnlineStatus;
1885 primOwner.NewestPrim = msg.PrimOwnersBlock[i].TimeStamp;
1886  
1887 primOwners.Add(primOwner);
1888 }
1889  
1890 OnParcelObjectOwnersReply(new ParcelObjectOwnersReplyEventArgs(simulator, primOwners));
1891 }
1892 }
1893  
1894 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1895 /// <param name="sender">The sender</param>
1896 /// <param name="e">The EventArgs object containing the packet data</param>
1897 /// <remarks>Raises the <see cref="ForceSelectObjectsReply"/> event</remarks>
1898 protected void SelectParcelObjectsReplyHandler(object sender, PacketReceivedEventArgs e)
1899 {
1900 if (m_ForceSelectObjects != null)
1901 {
1902 Packet packet = e.Packet;
1903 Simulator simulator = e.Simulator;
1904  
1905 ForceObjectSelectPacket reply = (ForceObjectSelectPacket)packet;
1906 List<uint> objectIDs = new List<uint>(reply.Data.Length);
1907  
1908 for (int i = 0; i < reply.Data.Length; i++)
1909 {
1910 objectIDs.Add(reply.Data[i].LocalID);
1911 }
1912  
1913 OnForceSelectObjectsReply(new ForceSelectObjectsReplyEventArgs(simulator, objectIDs, reply._Header.ResetList));
1914 }
1915 }
1916  
1917 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1918 /// <param name="sender">The sender</param>
1919 /// <param name="e">The EventArgs object containing the packet data</param>
1920 /// <remarks>Raises the <see cref="ParcelMediaUpdateReply"/> event</remarks>
1921 protected void ParcelMediaUpdateHandler(object sender, PacketReceivedEventArgs e)
1922 {
1923 if (m_ParcelMediaUpdateReply != null)
1924 {
1925 Packet packet = e.Packet;
1926 Simulator simulator = e.Simulator;
1927  
1928 ParcelMediaUpdatePacket reply = (ParcelMediaUpdatePacket)packet;
1929 ParcelMedia media = new ParcelMedia();
1930  
1931 media.MediaAutoScale = (reply.DataBlock.MediaAutoScale == (byte)0x1) ? true : false;
1932 media.MediaID = reply.DataBlock.MediaID;
1933 media.MediaDesc = Utils.BytesToString(reply.DataBlockExtended.MediaDesc);
1934 media.MediaHeight = reply.DataBlockExtended.MediaHeight;
1935 media.MediaLoop = ((reply.DataBlockExtended.MediaLoop & 1) != 0) ? true : false;
1936 media.MediaType = Utils.BytesToString(reply.DataBlockExtended.MediaType);
1937 media.MediaWidth = reply.DataBlockExtended.MediaWidth;
1938 media.MediaURL = Utils.BytesToString(reply.DataBlock.MediaURL);
1939  
1940 OnParcelMediaUpdateReply(new ParcelMediaUpdateReplyEventArgs(simulator, media));
1941 }
1942 }
1943  
1944 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1945 /// <param name="sender">The sender</param>
1946 /// <param name="e">The EventArgs object containing the packet data</param>
1947 protected void ParcelOverlayHandler(object sender, PacketReceivedEventArgs e)
1948 {
1949 const int OVERLAY_COUNT = 4;
1950 Packet packet = e.Packet;
1951 Simulator simulator = e.Simulator;
1952  
1953 ParcelOverlayPacket overlay = (ParcelOverlayPacket)packet;
1954  
1955 if (overlay.ParcelData.SequenceID >= 0 && overlay.ParcelData.SequenceID < OVERLAY_COUNT)
1956 {
1957 int length = overlay.ParcelData.Data.Length;
1958  
1959 Buffer.BlockCopy(overlay.ParcelData.Data, 0, simulator.ParcelOverlay,
1960 overlay.ParcelData.SequenceID * length, length);
1961 simulator.ParcelOverlaysReceived++;
1962  
1963 if (simulator.ParcelOverlaysReceived >= OVERLAY_COUNT)
1964 {
1965 // TODO: ParcelOverlaysReceived should become internal, and reset to zero every
1966 // time it hits four. Also need a callback here
1967 }
1968 }
1969 else
1970 {
1971 Logger.Log("Parcel overlay with sequence ID of " + overlay.ParcelData.SequenceID +
1972 " received from " + simulator.ToString(), Helpers.LogLevel.Warning, Client);
1973 }
1974 }
1975  
1976 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1977 /// <param name="sender">The sender</param>
1978 /// <param name="e">The EventArgs object containing the packet data</param>
1979 /// <remarks>Raises the <see cref="ParcelMediaCommand"/> event</remarks>
1980 protected void ParcelMediaCommandMessagePacketHandler(object sender, PacketReceivedEventArgs e)
1981 {
1982 if (m_ParcelMediaCommand != null)
1983 {
1984 Packet packet = e.Packet;
1985 Simulator simulator = e.Simulator;
1986  
1987 ParcelMediaCommandMessagePacket pmc = (ParcelMediaCommandMessagePacket)packet;
1988 ParcelMediaCommandMessagePacket.CommandBlockBlock block = pmc.CommandBlock;
1989  
1990 OnParcelMediaCommand(new ParcelMediaCommandEventArgs(simulator, pmc.Header.Sequence, (ParcelFlags)block.Flags,
1991 (ParcelMediaCommand)block.Command, block.Time));
1992 }
1993 }
1994  
1995 #endregion Packet Handlers
1996 }
1997 #region EventArgs classes
1998  
1999 /// <summary>Contains a parcels dwell data returned from the simulator in response to an <see cref="RequestParcelDwell"/></summary>
2000 public class ParcelDwellReplyEventArgs : EventArgs
2001 {
2002 private readonly UUID m_ParcelID;
2003 private readonly int m_LocalID;
2004 private readonly float m_Dwell;
2005  
2006 /// <summary>Get the global ID of the parcel</summary>
2007 public UUID ParcelID { get { return m_ParcelID; } }
2008 /// <summary>Get the simulator specific ID of the parcel</summary>
2009 public int LocalID { get { return m_LocalID; } }
2010 /// <summary>Get the calculated dwell</summary>
2011 public float Dwell { get { return m_Dwell; } }
2012  
2013 /// <summary>
2014 /// Construct a new instance of the ParcelDwellReplyEventArgs class
2015 /// </summary>
2016 /// <param name="parcelID">The global ID of the parcel</param>
2017 /// <param name="localID">The simulator specific ID of the parcel</param>
2018 /// <param name="dwell">The calculated dwell for the parcel</param>
2019 public ParcelDwellReplyEventArgs(UUID parcelID, int localID, float dwell)
2020 {
2021 this.m_ParcelID = parcelID;
2022 this.m_LocalID = localID;
2023 this.m_Dwell = dwell;
2024 }
2025 }
2026  
2027 /// <summary>Contains basic parcel information data returned from the
2028 /// simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
2029 public class ParcelInfoReplyEventArgs : EventArgs
2030 {
2031 private readonly ParcelInfo m_Parcel;
2032  
2033 /// <summary>Get the <see cref="ParcelInfo"/> object containing basic parcel info</summary>
2034 public ParcelInfo Parcel { get { return m_Parcel; } }
2035  
2036 /// <summary>
2037 /// Construct a new instance of the ParcelInfoReplyEventArgs class
2038 /// </summary>
2039 /// <param name="parcel">The <see cref="ParcelInfo"/> object containing basic parcel info</param>
2040 public ParcelInfoReplyEventArgs(ParcelInfo parcel)
2041 {
2042 this.m_Parcel = parcel;
2043 }
2044 }
2045  
2046 /// <summary>Contains basic parcel information data returned from the simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
2047 public class ParcelPropertiesEventArgs : EventArgs
2048 {
2049 private readonly Simulator m_Simulator;
2050 private Parcel m_Parcel;
2051 private readonly ParcelResult m_Result;
2052 private readonly int m_SelectedPrims;
2053 private readonly int m_SequenceID;
2054 private readonly bool m_SnapSelection;
2055  
2056 /// <summary>Get the simulator the parcel is located in</summary>
2057 public Simulator Simulator { get { return m_Simulator; } }
2058 /// <summary>Get the <see cref="Parcel"/> object containing the details</summary>
2059 /// <remarks>If Result is NoData, this object will not contain valid data</remarks>
2060 public Parcel Parcel { get { return m_Parcel; } }
2061 /// <summary>Get the result of the request</summary>
2062 public ParcelResult Result { get { return m_Result; } }
2063 /// <summary>Get the number of primitieves your agent is
2064 /// currently selecting and or sitting on in this parcel</summary>
2065 public int SelectedPrims { get { return m_SelectedPrims; } }
2066 /// <summary>Get the user assigned ID used to correlate a request with
2067 /// these results</summary>
2068 public int SequenceID { get { return m_SequenceID; } }
2069 /// <summary>TODO:</summary>
2070 public bool SnapSelection { get { return m_SnapSelection; } }
2071  
2072 /// <summary>
2073 /// Construct a new instance of the ParcelPropertiesEventArgs class
2074 /// </summary>
2075 /// <param name="simulator">The <see cref="Parcel"/> object containing the details</param>
2076 /// <param name="parcel">The <see cref="Parcel"/> object containing the details</param>
2077 /// <param name="result">The result of the request</param>
2078 /// <param name="selectedPrims">The number of primitieves your agent is
2079 /// currently selecting and or sitting on in this parcel</param>
2080 /// <param name="sequenceID">The user assigned ID used to correlate a request with
2081 /// these results</param>
2082 /// <param name="snapSelection">TODO:</param>
2083 public ParcelPropertiesEventArgs(Simulator simulator, Parcel parcel, ParcelResult result, int selectedPrims,
2084 int sequenceID, bool snapSelection)
2085 {
2086 this.m_Simulator = simulator;
2087 this.m_Parcel = parcel;
2088 this.m_Result = result;
2089 this.m_SelectedPrims = selectedPrims;
2090 this.m_SequenceID = sequenceID;
2091 this.m_SnapSelection = snapSelection;
2092 }
2093 }
2094  
2095 /// <summary>Contains blacklist and whitelist data returned from the simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
2096 public class ParcelAccessListReplyEventArgs : EventArgs
2097 {
2098 private readonly Simulator m_Simulator;
2099 private readonly int m_SequenceID;
2100 private readonly int m_LocalID;
2101 private readonly uint m_Flags;
2102 private readonly List<ParcelManager.ParcelAccessEntry> m_AccessList;
2103  
2104 /// <summary>Get the simulator the parcel is located in</summary>
2105 public Simulator Simulator { get { return m_Simulator; } }
2106 /// <summary>Get the user assigned ID used to correlate a request with
2107 /// these results</summary>
2108 public int SequenceID { get { return m_SequenceID; } }
2109 /// <summary>Get the simulator specific ID of the parcel</summary>
2110 public int LocalID { get { return m_LocalID; } }
2111 /// <summary>TODO:</summary>
2112 public uint Flags { get { return m_Flags; } }
2113 /// <summary>Get the list containing the white/blacklisted agents for the parcel</summary>
2114 public List<ParcelManager.ParcelAccessEntry> AccessList { get { return m_AccessList; } }
2115  
2116 /// <summary>
2117 /// Construct a new instance of the ParcelAccessListReplyEventArgs class
2118 /// </summary>
2119 /// <param name="simulator">The simulator the parcel is located in</param>
2120 /// <param name="sequenceID">The user assigned ID used to correlate a request with
2121 /// these results</param>
2122 /// <param name="localID">The simulator specific ID of the parcel</param>
2123 /// <param name="flags">TODO:</param>
2124 /// <param name="accessEntries">The list containing the white/blacklisted agents for the parcel</param>
2125 public ParcelAccessListReplyEventArgs(Simulator simulator, int sequenceID, int localID, uint flags, List<ParcelManager.ParcelAccessEntry> accessEntries)
2126 {
2127 this.m_Simulator = simulator;
2128 this.m_SequenceID = sequenceID;
2129 this.m_LocalID = localID;
2130 this.m_Flags = flags;
2131 this.m_AccessList = accessEntries;
2132 }
2133 }
2134  
2135 /// <summary>Contains blacklist and whitelist data returned from the
2136 /// simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
2137 public class ParcelObjectOwnersReplyEventArgs : EventArgs
2138 {
2139 private readonly Simulator m_Simulator;
2140 private readonly List<ParcelManager.ParcelPrimOwners> m_Owners;
2141  
2142 /// <summary>Get the simulator the parcel is located in</summary>
2143 public Simulator Simulator { get { return m_Simulator; } }
2144 /// <summary>Get the list containing prim ownership counts</summary>
2145 public List<ParcelManager.ParcelPrimOwners> PrimOwners { get { return m_Owners; } }
2146  
2147 /// <summary>
2148 /// Construct a new instance of the ParcelObjectOwnersReplyEventArgs class
2149 /// </summary>
2150 /// <param name="simulator">The simulator the parcel is located in</param>
2151 /// <param name="primOwners">The list containing prim ownership counts</param>
2152 public ParcelObjectOwnersReplyEventArgs(Simulator simulator, List<ParcelManager.ParcelPrimOwners> primOwners)
2153 {
2154 this.m_Simulator = simulator;
2155 this.m_Owners = primOwners;
2156 }
2157 }
2158  
2159 /// <summary>Contains the data returned when all parcel data has been retrieved from a simulator</summary>
2160 public class SimParcelsDownloadedEventArgs : EventArgs
2161 {
2162 private readonly Simulator m_Simulator;
2163 private readonly InternalDictionary<int, Parcel> m_Parcels;
2164 private readonly int[,] m_ParcelMap;
2165  
2166 /// <summary>Get the simulator the parcel data was retrieved from</summary>
2167 public Simulator Simulator { get { return m_Simulator; } }
2168 /// <summary>A dictionary containing the parcel data where the key correlates to the ParcelMap entry</summary>
2169 public InternalDictionary<int, Parcel> Parcels { get { return m_Parcels; } }
2170 /// <summary>Get the multidimensional array containing a x,y grid mapped
2171 /// to each 64x64 parcel's LocalID.</summary>
2172 public int[,] ParcelMap { get { return m_ParcelMap; } }
2173  
2174 /// <summary>
2175 /// Construct a new instance of the SimParcelsDownloadedEventArgs class
2176 /// </summary>
2177 /// <param name="simulator">The simulator the parcel data was retrieved from</param>
2178 /// <param name="simParcels">The dictionary containing the parcel data</param>
2179 /// <param name="parcelMap">The multidimensional array containing a x,y grid mapped
2180 /// to each 64x64 parcel's LocalID.</param>
2181 public SimParcelsDownloadedEventArgs(Simulator simulator, InternalDictionary<int, Parcel> simParcels, int[,] parcelMap)
2182 {
2183 this.m_Simulator = simulator;
2184 this.m_Parcels = simParcels;
2185 this.m_ParcelMap = parcelMap;
2186 }
2187 }
2188  
2189 /// <summary>Contains the data returned when a <see cref="RequestForceSelectObjects"/> request</summary>
2190 public class ForceSelectObjectsReplyEventArgs : EventArgs
2191 {
2192 private readonly Simulator m_Simulator;
2193 private readonly List<uint> m_ObjectIDs;
2194 private readonly bool m_ResetList;
2195  
2196 /// <summary>Get the simulator the parcel data was retrieved from</summary>
2197 public Simulator Simulator { get { return m_Simulator; } }
2198 /// <summary>Get the list of primitive IDs</summary>
2199 public List<uint> ObjectIDs { get { return m_ObjectIDs; } }
2200 /// <summary>true if the list is clean and contains the information
2201 /// only for a given request</summary>
2202 public bool ResetList { get { return m_ResetList; } }
2203  
2204 /// <summary>
2205 /// Construct a new instance of the ForceSelectObjectsReplyEventArgs class
2206 /// </summary>
2207 /// <param name="simulator">The simulator the parcel data was retrieved from</param>
2208 /// <param name="objectIDs">The list of primitive IDs</param>
2209 /// <param name="resetList">true if the list is clean and contains the information
2210 /// only for a given request</param>
2211 public ForceSelectObjectsReplyEventArgs(Simulator simulator, List<uint> objectIDs, bool resetList)
2212 {
2213 this.m_Simulator = simulator;
2214 this.m_ObjectIDs = objectIDs;
2215 this.m_ResetList = resetList;
2216 }
2217 }
2218  
2219 /// <summary>Contains data when the media data for a parcel the avatar is on changes</summary>
2220 public class ParcelMediaUpdateReplyEventArgs : EventArgs
2221 {
2222 private readonly Simulator m_Simulator;
2223 private readonly ParcelMedia m_ParcelMedia;
2224  
2225 /// <summary>Get the simulator the parcel media data was updated in</summary>
2226 public Simulator Simulator { get { return m_Simulator; } }
2227 /// <summary>Get the updated media information</summary>
2228 public ParcelMedia Media { get { return m_ParcelMedia; } }
2229  
2230 /// <summary>
2231 /// Construct a new instance of the ParcelMediaUpdateReplyEventArgs class
2232 /// </summary>
2233 /// <param name="simulator">the simulator the parcel media data was updated in</param>
2234 /// <param name="media">The updated media information</param>
2235 public ParcelMediaUpdateReplyEventArgs(Simulator simulator, ParcelMedia media)
2236 {
2237 this.m_Simulator = simulator;
2238 this.m_ParcelMedia = media;
2239 }
2240 }
2241  
2242 /// <summary>Contains the media command for a parcel the agent is currently on</summary>
2243 public class ParcelMediaCommandEventArgs : EventArgs
2244 {
2245 private readonly Simulator m_Simulator;
2246 private readonly uint m_Sequence;
2247 private readonly ParcelFlags m_ParcelFlags;
2248 private readonly ParcelMediaCommand m_MediaCommand;
2249 private readonly float m_Time;
2250  
2251 /// <summary>Get the simulator the parcel media command was issued in</summary>
2252 public Simulator Simulator { get { return m_Simulator; } }
2253 /// <summary></summary>
2254 public uint Sequence { get { return m_Sequence; } }
2255 /// <summary></summary>
2256 public ParcelFlags ParcelFlags { get { return m_ParcelFlags; } }
2257 /// <summary>Get the media command that was sent</summary>
2258 public ParcelMediaCommand MediaCommand { get { return m_MediaCommand; } }
2259 /// <summary></summary>
2260 public float Time { get { return m_Time; } }
2261  
2262 /// <summary>
2263 /// Construct a new instance of the ParcelMediaCommandEventArgs class
2264 /// </summary>
2265 /// <param name="simulator">The simulator the parcel media command was issued in</param>
2266 /// <param name="sequence"></param>
2267 /// <param name="flags"></param>
2268 /// <param name="command">The media command that was sent</param>
2269 /// <param name="time"></param>
2270 public ParcelMediaCommandEventArgs(Simulator simulator, uint sequence, ParcelFlags flags, ParcelMediaCommand command, float time)
2271 {
2272 this.m_Simulator = simulator;
2273 this.m_Sequence = sequence;
2274 this.m_ParcelFlags = flags;
2275 this.m_MediaCommand = command;
2276 this.m_Time = time;
2277 }
2278 }
2279 #endregion
2280 }