corrade-vassal – Blame information for rev 16

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;
16 eva 572 /// <summary> true if avatars in this parcel should be invisible to people outside</summary>
573 public bool SeeAVs;
574 /// <summary> true if avatars outside can hear any sounds avatars inside play</summary>
575 public bool AnyAVSounds;
576 /// <summary> true if group members outside can hear any sounds avatars inside play</summary>
577 public bool GroupAVSounds;
1 vero 578  
579 /// <summary>
580 /// Displays a parcel object in string format
581 /// </summary>
582 /// <returns>string containing key=value pairs of a parcel object</returns>
583 public override string ToString()
584 {
585 string result = "";
586 Type parcelType = this.GetType();
587 FieldInfo[] fields = parcelType.GetFields();
588 foreach (FieldInfo field in fields)
589 {
590 result += (field.Name + " = " + field.GetValue(this) + " ");
591 }
592 return result;
593 }
594 /// <summary>
595 /// Defalt constructor
596 /// </summary>
597 /// <param name="localID">Local ID of this parcel</param>
598 public Parcel(int localID)
599 {
600 LocalID = localID;
601 ClaimDate = Utils.Epoch;
602 Bitmap = Utils.EmptyBytes;
603 Name = String.Empty;
604 Desc = String.Empty;
605 MusicURL = String.Empty;
606 AccessWhiteList = new List<ParcelManager.ParcelAccessEntry>(0);
607 AccessBlackList = new List<ParcelManager.ParcelAccessEntry>(0);
608 Media = new ParcelMedia();
609 }
610  
611 /// <summary>
612 /// Update the simulator with any local changes to this Parcel object
613 /// </summary>
614 /// <param name="simulator">Simulator to send updates to</param>
615 /// <param name="wantReply">Whether we want the simulator to confirm
616 /// the update with a reply packet or not</param>
617 public void Update(Simulator simulator, bool wantReply)
618 {
619 Uri url = simulator.Caps.CapabilityURI("ParcelPropertiesUpdate");
620  
621 if (url != null)
622 {
623 ParcelPropertiesUpdateMessage req = new ParcelPropertiesUpdateMessage();
624 req.AuthBuyerID = this.AuthBuyerID;
625 req.Category = this.Category;
626 req.Desc = this.Desc;
627 req.GroupID = this.GroupID;
628 req.Landing = this.Landing;
629 req.LocalID = this.LocalID;
630 req.MediaAutoScale = this.Media.MediaAutoScale;
631 req.MediaDesc = this.Media.MediaDesc;
632 req.MediaHeight = this.Media.MediaHeight;
633 req.MediaID = this.Media.MediaID;
634 req.MediaLoop = this.Media.MediaLoop;
635 req.MediaType = this.Media.MediaType;
636 req.MediaURL = this.Media.MediaURL;
637 req.MediaWidth = this.Media.MediaWidth;
638 req.MusicURL = this.MusicURL;
639 req.Name = this.Name;
640 req.ObscureMedia = this.ObscureMedia;
641 req.ObscureMusic = this.ObscureMusic;
642 req.ParcelFlags = this.Flags;
643 req.PassHours = this.PassHours;
644 req.PassPrice = (uint)this.PassPrice;
645 req.SalePrice = (uint)this.SalePrice;
646 req.SnapshotID = this.SnapshotID;
647 req.UserLocation = this.UserLocation;
648 req.UserLookAt = this.UserLookAt;
16 eva 649 req.SeeAVs = this.SeeAVs;
650 req.AnyAVSounds = this.AnyAVSounds;
651 req.GroupAVSounds = this.GroupAVSounds;
652  
1 vero 653 OSDMap body = req.Serialize();
654  
655 CapsClient capsPost = new CapsClient(url);
656 capsPost.BeginGetResponse(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
657 }
658 else
659 {
660 ParcelPropertiesUpdatePacket request = new ParcelPropertiesUpdatePacket();
661  
662 request.AgentData.AgentID = simulator.Client.Self.AgentID;
663 request.AgentData.SessionID = simulator.Client.Self.SessionID;
664  
665 request.ParcelData.LocalID = this.LocalID;
666  
667 request.ParcelData.AuthBuyerID = this.AuthBuyerID;
668 request.ParcelData.Category = (byte)this.Category;
669 request.ParcelData.Desc = Utils.StringToBytes(this.Desc);
670 request.ParcelData.GroupID = this.GroupID;
671 request.ParcelData.LandingType = (byte)this.Landing;
672 request.ParcelData.MediaAutoScale = (this.Media.MediaAutoScale) ? (byte)0x1 : (byte)0x0;
673 request.ParcelData.MediaID = this.Media.MediaID;
674 request.ParcelData.MediaURL = Utils.StringToBytes(this.Media.MediaURL.ToString());
675 request.ParcelData.MusicURL = Utils.StringToBytes(this.MusicURL.ToString());
676 request.ParcelData.Name = Utils.StringToBytes(this.Name);
677 if (wantReply) request.ParcelData.Flags = 1;
678 request.ParcelData.ParcelFlags = (uint)this.Flags;
679 request.ParcelData.PassHours = this.PassHours;
680 request.ParcelData.PassPrice = this.PassPrice;
681 request.ParcelData.SalePrice = this.SalePrice;
682 request.ParcelData.SnapshotID = this.SnapshotID;
683 request.ParcelData.UserLocation = this.UserLocation;
684 request.ParcelData.UserLookAt = this.UserLookAt;
685  
686 simulator.SendPacket(request);
687 }
688  
689 UpdateOtherCleanTime(simulator);
690  
691 }
692  
693 /// <summary>
694 /// Set Autoreturn time
695 /// </summary>
696 /// <param name="simulator">Simulator to send the update to</param>
697 public void UpdateOtherCleanTime(Simulator simulator)
698 {
699 ParcelSetOtherCleanTimePacket request = new ParcelSetOtherCleanTimePacket();
700 request.AgentData.AgentID = simulator.Client.Self.AgentID;
701 request.AgentData.SessionID = simulator.Client.Self.SessionID;
702 request.ParcelData.LocalID = this.LocalID;
703 request.ParcelData.OtherCleanTime = this.OtherCleanTime;
704  
705 simulator.SendPacket(request);
706 }
707 }
708  
709 #endregion Parcel Class
710  
711 /// <summary>
712 /// Parcel (subdivided simulator lots) subsystem
713 /// </summary>
714 public class ParcelManager
715 {
716 #region Structs
717  
718 /// <summary>
719 /// Parcel Accesslist
720 /// </summary>
721 public struct ParcelAccessEntry
722 {
723 /// <summary>Agents <seealso cref="T:OpenMetaverse.UUID"/></summary>
724 public UUID AgentID;
725 /// <summary></summary>
726 public DateTime Time;
727 /// <summary>Flags for specific entry in white/black lists</summary>
728 public AccessList Flags;
729 }
730  
731 /// <summary>
732 /// Owners of primitives on parcel
733 /// </summary>
734 public struct ParcelPrimOwners
735 {
736 /// <summary>Prim Owners <seealso cref="T:OpenMetaverse.UUID"/></summary>
737 public UUID OwnerID;
738 /// <summary>True of owner is group</summary>
739 public bool IsGroupOwned;
740 /// <summary>Total count of prims owned by OwnerID</summary>
741 public int Count;
742 /// <summary>true of OwnerID is currently online and is not a group</summary>
743 public bool OnlineStatus;
744 /// <summary>The date of the most recent prim left by OwnerID</summary>
745 public DateTime NewestPrim;
746 }
747  
748 #endregion Structs
749  
750 #region Delegates
751 /// <summary>
752 /// Called once parcel resource usage information has been collected
753 /// </summary>
754 /// <param name="success">Indicates if operation was successfull</param>
755 /// <param name="info">Parcel resource usage information</param>
756 public delegate void LandResourcesCallback(bool success, LandResourcesInfo info);
757  
758 /// <summary>The event subscribers. null if no subcribers</summary>
759 private EventHandler<ParcelDwellReplyEventArgs> m_DwellReply;
760  
761 /// <summary>Raises the ParcelDwellReply event</summary>
762 /// <param name="e">A ParcelDwellReplyEventArgs object containing the
763 /// data returned from the simulator</param>
764 protected virtual void OnParcelDwellReply(ParcelDwellReplyEventArgs e)
765 {
766 EventHandler<ParcelDwellReplyEventArgs> handler = m_DwellReply;
767 if (handler != null)
768 handler(this, e);
769 }
770  
771 /// <summary>Thread sync lock object</summary>
772 private readonly object m_DwellReplyLock = new object();
773  
774 /// <summary>Raised when the simulator responds to a <see cref="RequestDwell"/> request</summary>
775 public event EventHandler<ParcelDwellReplyEventArgs> ParcelDwellReply
776 {
777 add { lock (m_DwellReplyLock) { m_DwellReply += value; } }
778 remove { lock (m_DwellReplyLock) { m_DwellReply -= value; } }
779 }
780  
781 /// <summary>The event subscribers. null if no subcribers</summary>
782 private EventHandler<ParcelInfoReplyEventArgs> m_ParcelInfo;
783  
784 /// <summary>Raises the ParcelInfoReply event</summary>
785 /// <param name="e">A ParcelInfoReplyEventArgs object containing the
786 /// data returned from the simulator</param>
787 protected virtual void OnParcelInfoReply(ParcelInfoReplyEventArgs e)
788 {
789 EventHandler<ParcelInfoReplyEventArgs> handler = m_ParcelInfo;
790 if (handler != null)
791 handler(this, e);
792 }
793  
794 /// <summary>Thread sync lock object</summary>
795 private readonly object m_ParcelInfoLock = new object();
796  
797 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelInfo"/> request</summary>
798 public event EventHandler<ParcelInfoReplyEventArgs> ParcelInfoReply
799 {
800 add { lock (m_ParcelInfoLock) { m_ParcelInfo += value; } }
801 remove { lock (m_ParcelInfoLock) { m_ParcelInfo -= value; } }
802 }
803  
804 /// <summary>The event subscribers. null if no subcribers</summary>
805 private EventHandler<ParcelPropertiesEventArgs> m_ParcelProperties;
806  
807 /// <summary>Raises the ParcelProperties event</summary>
808 /// <param name="e">A ParcelPropertiesEventArgs object containing the
809 /// data returned from the simulator</param>
810 protected virtual void OnParcelProperties(ParcelPropertiesEventArgs e)
811 {
812 EventHandler<ParcelPropertiesEventArgs> handler = m_ParcelProperties;
813 if (handler != null)
814 handler(this, e);
815 }
816  
817 /// <summary>Thread sync lock object</summary>
818 private readonly object m_ParcelPropertiesLock = new object();
819  
820 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelProperties"/> request</summary>
821 public event EventHandler<ParcelPropertiesEventArgs> ParcelProperties
822 {
823 add { lock (m_ParcelPropertiesLock) { m_ParcelProperties += value; } }
824 remove { lock (m_ParcelPropertiesLock) { m_ParcelProperties -= value; } }
825 }
826  
827 /// <summary>The event subscribers. null if no subcribers</summary>
828 private EventHandler<ParcelAccessListReplyEventArgs> m_ParcelACL;
829  
830 /// <summary>Raises the ParcelAccessListReply event</summary>
831 /// <param name="e">A ParcelAccessListReplyEventArgs object containing the
832 /// data returned from the simulator</param>
833 protected virtual void OnParcelAccessListReply(ParcelAccessListReplyEventArgs e)
834 {
835 EventHandler<ParcelAccessListReplyEventArgs> handler = m_ParcelACL;
836 if (handler != null)
837 handler(this, e);
838 }
839  
840 /// <summary>Thread sync lock object</summary>
841 private readonly object m_ParcelACLLock = new object();
842  
843 /// <summary>Raised when the simulator responds to a <see cref="RequestParcelAccessList"/> request</summary>
844 public event EventHandler<ParcelAccessListReplyEventArgs> ParcelAccessListReply
845 {
846 add { lock (m_ParcelACLLock) { m_ParcelACL += value; } }
847 remove { lock (m_ParcelACLLock) { m_ParcelACL -= value; } }
848 }
849  
850 /// <summary>The event subscribers. null if no subcribers</summary>
851 private EventHandler<ParcelObjectOwnersReplyEventArgs> m_ParcelObjectOwnersReply;
852  
853 /// <summary>Raises the ParcelObjectOwnersReply event</summary>
854 /// <param name="e">A ParcelObjectOwnersReplyEventArgs object containing the
855 /// data returned from the simulator</param>
856 protected virtual void OnParcelObjectOwnersReply(ParcelObjectOwnersReplyEventArgs e)
857 {
858 EventHandler<ParcelObjectOwnersReplyEventArgs> handler = m_ParcelObjectOwnersReply;
859 if (handler != null)
860 handler(this, e);
861 }
862  
863 /// <summary>Thread sync lock object</summary>
864 private readonly object m_ParcelObjectOwnersLock = new object();
865  
866 /// <summary>Raised when the simulator responds to a <see cref="RequestObjectOwners"/> request</summary>
867 public event EventHandler<ParcelObjectOwnersReplyEventArgs> ParcelObjectOwnersReply
868 {
869 add { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply += value; } }
870 remove { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply -= value; } }
871 }
872  
873 /// <summary>The event subscribers. null if no subcribers</summary>
874 private EventHandler<SimParcelsDownloadedEventArgs> m_SimParcelsDownloaded;
875  
876 /// <summary>Raises the SimParcelsDownloaded event</summary>
877 /// <param name="e">A SimParcelsDownloadedEventArgs object containing the
878 /// data returned from the simulator</param>
879 protected virtual void OnSimParcelsDownloaded(SimParcelsDownloadedEventArgs e)
880 {
881 EventHandler<SimParcelsDownloadedEventArgs> handler = m_SimParcelsDownloaded;
882 if (handler != null)
883 handler(this, e);
884 }
885  
886 /// <summary>Thread sync lock object</summary>
887 private readonly object m_SimParcelsDownloadedLock = new object();
888  
889 /// <summary>Raised when the simulator responds to a <see cref="RequestAllSimParcels"/> request</summary>
890 public event EventHandler<SimParcelsDownloadedEventArgs> SimParcelsDownloaded
891 {
892 add { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded += value; } }
893 remove { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded -= value; } }
894 }
895  
896 /// <summary>The event subscribers. null if no subcribers</summary>
897 private EventHandler<ForceSelectObjectsReplyEventArgs> m_ForceSelectObjects;
898  
899 /// <summary>Raises the ForceSelectObjectsReply event</summary>
900 /// <param name="e">A ForceSelectObjectsReplyEventArgs object containing the
901 /// data returned from the simulator</param>
902 protected virtual void OnForceSelectObjectsReply(ForceSelectObjectsReplyEventArgs e)
903 {
904 EventHandler<ForceSelectObjectsReplyEventArgs> handler = m_ForceSelectObjects;
905 if (handler != null)
906 handler(this, e);
907 }
908  
909 /// <summary>Thread sync lock object</summary>
910 private readonly object m_ForceSelectObjectsLock = new object();
911  
912 /// <summary>Raised when the simulator responds to a <see cref="RequestForceSelectObjects"/> request</summary>
913 public event EventHandler<ForceSelectObjectsReplyEventArgs> ForceSelectObjectsReply
914 {
915 add { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects += value; } }
916 remove { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects -= value; } }
917 }
918  
919 /// <summary>The event subscribers. null if no subcribers</summary>
920 private EventHandler<ParcelMediaUpdateReplyEventArgs> m_ParcelMediaUpdateReply;
921  
922 /// <summary>Raises the ParcelMediaUpdateReply event</summary>
923 /// <param name="e">A ParcelMediaUpdateReplyEventArgs object containing the
924 /// data returned from the simulator</param>
925 protected virtual void OnParcelMediaUpdateReply(ParcelMediaUpdateReplyEventArgs e)
926 {
927 EventHandler<ParcelMediaUpdateReplyEventArgs> handler = m_ParcelMediaUpdateReply;
928 if (handler != null)
929 handler(this, e);
930 }
931  
932 /// <summary>Thread sync lock object</summary>
933 private readonly object m_ParcelMediaUpdateReplyLock = new object();
934  
935 /// <summary>Raised when the simulator responds to a Parcel Update request</summary>
936 public event EventHandler<ParcelMediaUpdateReplyEventArgs> ParcelMediaUpdateReply
937 {
938 add { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply += value; } }
939 remove { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply -= value; } }
940 }
941  
942 /// <summary>The event subscribers. null if no subcribers</summary>
943 private EventHandler<ParcelMediaCommandEventArgs> m_ParcelMediaCommand;
944  
945 /// <summary>Raises the ParcelMediaCommand event</summary>
946 /// <param name="e">A ParcelMediaCommandEventArgs object containing the
947 /// data returned from the simulator</param>
948 protected virtual void OnParcelMediaCommand(ParcelMediaCommandEventArgs e)
949 {
950 EventHandler<ParcelMediaCommandEventArgs> handler = m_ParcelMediaCommand;
951 if (handler != null)
952 handler(this, e);
953 }
954  
955 /// <summary>Thread sync lock object</summary>
956 private readonly object m_ParcelMediaCommandLock = new object();
957  
958 /// <summary>Raised when the parcel your agent is located sends a ParcelMediaCommand</summary>
959 public event EventHandler<ParcelMediaCommandEventArgs> ParcelMediaCommand
960 {
961 add { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand += value; } }
962 remove { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand -= value; } }
963 }
964 #endregion Delegates
965  
966 private GridClient Client;
967 private AutoResetEvent WaitForSimParcel;
968  
969 #region Public Methods
970  
971 /// <summary>
972 /// Default constructor
973 /// </summary>
974 /// <param name="client">A reference to the GridClient object</param>
975 public ParcelManager(GridClient client)
976 {
977 Client = client;
978  
979 // Setup the callbacks
980 Client.Network.RegisterCallback(PacketType.ParcelInfoReply, ParcelInfoReplyHandler);
981 Client.Network.RegisterEventCallback("ParcelObjectOwnersReply", new Caps.EventQueueCallback(ParcelObjectOwnersReplyHandler));
982 // CAPS packet handler, to allow for Media Data not contained in the message template
983 Client.Network.RegisterEventCallback("ParcelProperties", new Caps.EventQueueCallback(ParcelPropertiesReplyHandler));
984 Client.Network.RegisterCallback(PacketType.ParcelDwellReply, ParcelDwellReplyHandler);
985 Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, ParcelAccessListReplyHandler);
986 Client.Network.RegisterCallback(PacketType.ForceObjectSelect, SelectParcelObjectsReplyHandler);
987 Client.Network.RegisterCallback(PacketType.ParcelMediaUpdate, ParcelMediaUpdateHandler);
988 Client.Network.RegisterCallback(PacketType.ParcelOverlay, ParcelOverlayHandler);
989 Client.Network.RegisterCallback(PacketType.ParcelMediaCommandMessage, ParcelMediaCommandMessagePacketHandler);
990 }
991  
992 /// <summary>
993 /// Request basic information for a single parcel
994 /// </summary>
995 /// <param name="parcelID">Simulator-local ID of the parcel</param>
996 public void RequestParcelInfo(UUID parcelID)
997 {
998 ParcelInfoRequestPacket request = new ParcelInfoRequestPacket();
999 request.AgentData.AgentID = Client.Self.AgentID;
1000 request.AgentData.SessionID = Client.Self.SessionID;
1001 request.Data.ParcelID = parcelID;
1002  
1003 Client.Network.SendPacket(request);
1004 }
1005  
1006 /// <summary>
1007 /// Request properties of a single parcel
1008 /// </summary>
1009 /// <param name="simulator">Simulator containing the parcel</param>
1010 /// <param name="localID">Simulator-local ID of the parcel</param>
1011 /// <param name="sequenceID">An arbitrary integer that will be returned
1012 /// with the ParcelProperties reply, useful for distinguishing between
1013 /// multiple simultaneous requests</param>
1014 public void RequestParcelProperties(Simulator simulator, int localID, int sequenceID)
1015 {
1016 ParcelPropertiesRequestByIDPacket request = new ParcelPropertiesRequestByIDPacket();
1017  
1018 request.AgentData.AgentID = Client.Self.AgentID;
1019 request.AgentData.SessionID = Client.Self.SessionID;
1020  
1021 request.ParcelData.LocalID = localID;
1022 request.ParcelData.SequenceID = sequenceID;
1023  
1024 Client.Network.SendPacket(request, simulator);
1025 }
1026  
1027 /// <summary>
1028 /// Request the access list for a single parcel
1029 /// </summary>
1030 /// <param name="simulator">Simulator containing the parcel</param>
1031 /// <param name="localID">Simulator-local ID of the parcel</param>
1032 /// <param name="sequenceID">An arbitrary integer that will be returned
1033 /// with the ParcelAccessList reply, useful for distinguishing between
1034 /// multiple simultaneous requests</param>
1035 /// <param name="flags"></param>
1036 public void RequestParcelAccessList(Simulator simulator, int localID, AccessList flags, int sequenceID)
1037 {
1038 ParcelAccessListRequestPacket request = new ParcelAccessListRequestPacket();
1039  
1040 request.AgentData.AgentID = Client.Self.AgentID;
1041 request.AgentData.SessionID = Client.Self.SessionID;
1042 request.Data.LocalID = localID;
1043 request.Data.Flags = (uint)flags;
1044 request.Data.SequenceID = sequenceID;
1045  
1046 Client.Network.SendPacket(request, simulator);
1047 }
1048  
1049 /// <summary>
1050 /// Request properties of parcels using a bounding box selection
1051 /// </summary>
1052 /// <param name="simulator">Simulator containing the parcel</param>
1053 /// <param name="north">Northern boundary of the parcel selection</param>
1054 /// <param name="east">Eastern boundary of the parcel selection</param>
1055 /// <param name="south">Southern boundary of the parcel selection</param>
1056 /// <param name="west">Western boundary of the parcel selection</param>
1057 /// <param name="sequenceID">An arbitrary integer that will be returned
1058 /// with the ParcelProperties reply, useful for distinguishing between
1059 /// different types of parcel property requests</param>
1060 /// <param name="snapSelection">A boolean that is returned with the
1061 /// ParcelProperties reply, useful for snapping focus to a single
1062 /// parcel</param>
1063 public void RequestParcelProperties(Simulator simulator, float north, float east, float south, float west,
1064 int sequenceID, bool snapSelection)
1065 {
1066 ParcelPropertiesRequestPacket request = new ParcelPropertiesRequestPacket();
1067  
1068 request.AgentData.AgentID = Client.Self.AgentID;
1069 request.AgentData.SessionID = Client.Self.SessionID;
1070 request.ParcelData.North = north;
1071 request.ParcelData.East = east;
1072 request.ParcelData.South = south;
1073 request.ParcelData.West = west;
1074 request.ParcelData.SequenceID = sequenceID;
1075 request.ParcelData.SnapSelection = snapSelection;
1076  
1077 Client.Network.SendPacket(request, simulator);
1078 }
1079  
1080 /// <summary>
1081 /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
1082 /// dictionary)
1083 /// </summary>
1084 /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
1085 public void RequestAllSimParcels(Simulator simulator)
1086 {
1087 RequestAllSimParcels(simulator, false, 750);
1088 }
1089  
1090 /// <summary>
1091 /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
1092 /// dictionary)
1093 /// </summary>
1094 /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
1095 /// <param name="refresh">If TRUE, will force a full refresh</param>
1096 /// <param name="msDelay">Number of milliseconds to pause in between each request</param>
1097 public void RequestAllSimParcels(Simulator simulator, bool refresh, int msDelay)
1098 {
1099 if (simulator.DownloadingParcelMap)
1100 {
1101 Logger.Log("Already downloading parcels in " + simulator.Name, Helpers.LogLevel.Info, Client);
1102 return;
1103 }
1104 else
1105 {
1106 simulator.DownloadingParcelMap = true;
1107 WaitForSimParcel = new AutoResetEvent(false);
1108 }
1109  
1110 if (refresh)
1111 {
1112 for (int y = 0; y < 64; y++)
1113 for (int x = 0; x < 64; x++)
1114 simulator.ParcelMap[y, x] = 0;
1115 }
1116  
1117 Thread th = new Thread(delegate()
1118 {
1119 int count = 0, timeouts = 0, y, x;
1120  
1121 for (y = 0; y < 64; y++)
1122 {
1123 for (x = 0; x < 64; x++)
1124 {
1125 if (!Client.Network.Connected)
1126 return;
1127  
1128 if (simulator.ParcelMap[y, x] == 0)
1129 {
1130 Client.Parcels.RequestParcelProperties(simulator,
1131 (y + 1) * 4.0f, (x + 1) * 4.0f,
1132 y * 4.0f, x * 4.0f, int.MaxValue, false);
1133  
1134 // Wait the given amount of time for a reply before sending the next request
1135 if (!WaitForSimParcel.WaitOne(msDelay, false))
1136 ++timeouts;
1137  
1138 ++count;
1139 }
1140 }
1141 }
1142  
1143 Logger.Log(String.Format(
1144 "Full simulator parcel information retrieved. Sent {0} parcel requests. Current outgoing queue: {1}, Retry Count {2}",
1145 count, Client.Network.OutboxCount, timeouts), Helpers.LogLevel.Info, Client);
1146  
1147 simulator.DownloadingParcelMap = false;
1148 });
1149  
1150 th.Start();
1151 }
1152  
1153 /// <summary>
1154 /// Request the dwell value for a parcel
1155 /// </summary>
1156 /// <param name="simulator">Simulator containing the parcel</param>
1157 /// <param name="localID">Simulator-local ID of the parcel</param>
1158 public void RequestDwell(Simulator simulator, int localID)
1159 {
1160 ParcelDwellRequestPacket request = new ParcelDwellRequestPacket();
1161 request.AgentData.AgentID = Client.Self.AgentID;
1162 request.AgentData.SessionID = Client.Self.SessionID;
1163 request.Data.LocalID = localID;
1164 request.Data.ParcelID = UUID.Zero; // Not used by clients
1165  
1166 Client.Network.SendPacket(request, simulator);
1167 }
1168  
1169 /// <summary>
1170 /// Send a request to Purchase a parcel of land
1171 /// </summary>
1172 /// <param name="simulator">The Simulator the parcel is located in</param>
1173 /// <param name="localID">The parcels region specific local ID</param>
1174 /// <param name="forGroup">true if this parcel is being purchased by a group</param>
1175 /// <param name="groupID">The groups <seealso cref="T:OpenMetaverse.UUID"/></param>
1176 /// <param name="removeContribution">true to remove tier contribution if purchase is successful</param>
1177 /// <param name="parcelArea">The parcels size</param>
1178 /// <param name="parcelPrice">The purchase price of the parcel</param>
1179 /// <returns></returns>
1180 public void Buy(Simulator simulator, int localID, bool forGroup, UUID groupID,
1181 bool removeContribution, int parcelArea, int parcelPrice)
1182 {
1183 ParcelBuyPacket request = new ParcelBuyPacket();
1184  
1185 request.AgentData.AgentID = Client.Self.AgentID;
1186 request.AgentData.SessionID = Client.Self.SessionID;
1187  
1188 request.Data.Final = true;
1189 request.Data.GroupID = groupID;
1190 request.Data.LocalID = localID;
1191 request.Data.IsGroupOwned = forGroup;
1192 request.Data.RemoveContribution = removeContribution;
1193  
1194 request.ParcelData.Area = parcelArea;
1195 request.ParcelData.Price = parcelPrice;
1196  
1197 Client.Network.SendPacket(request, simulator);
1198 }
1199  
1200 /// <summary>
1201 /// Reclaim a parcel of land
1202 /// </summary>
1203 /// <param name="simulator">The simulator the parcel is in</param>
1204 /// <param name="localID">The parcels region specific local ID</param>
1205 public void Reclaim(Simulator simulator, int localID)
1206 {
1207 ParcelReclaimPacket request = new ParcelReclaimPacket();
1208 request.AgentData.AgentID = Client.Self.AgentID;
1209 request.AgentData.SessionID = Client.Self.SessionID;
1210  
1211 request.Data.LocalID = localID;
1212  
1213 Client.Network.SendPacket(request, simulator);
1214 }
1215  
1216 /// <summary>
1217 /// Deed a parcel to a group
1218 /// </summary>
1219 /// <param name="simulator">The simulator the parcel is in</param>
1220 /// <param name="localID">The parcels region specific local ID</param>
1221 /// <param name="groupID">The groups <seealso cref="T:OpenMetaverse.UUID"/></param>
1222 public void DeedToGroup(Simulator simulator, int localID, UUID groupID)
1223 {
1224 ParcelDeedToGroupPacket request = new ParcelDeedToGroupPacket();
1225 request.AgentData.AgentID = Client.Self.AgentID;
1226 request.AgentData.SessionID = Client.Self.SessionID;
1227  
1228 request.Data.LocalID = localID;
1229 request.Data.GroupID = groupID;
1230  
1231 Client.Network.SendPacket(request, simulator);
1232 }
1233  
1234 /// <summary>
1235 /// Request prim owners of a parcel of land.
1236 /// </summary>
1237 /// <param name="simulator">Simulator parcel is in</param>
1238 /// <param name="localID">The parcels region specific local ID</param>
1239 public void RequestObjectOwners(Simulator simulator, int localID)
1240 {
1241 ParcelObjectOwnersRequestPacket request = new ParcelObjectOwnersRequestPacket();
1242  
1243 request.AgentData.AgentID = Client.Self.AgentID;
1244 request.AgentData.SessionID = Client.Self.SessionID;
1245  
1246 request.ParcelData.LocalID = localID;
1247 Client.Network.SendPacket(request, simulator);
1248 }
1249  
1250 /// <summary>
1251 /// Return objects from a parcel
1252 /// </summary>
1253 /// <param name="simulator">Simulator parcel is in</param>
1254 /// <param name="localID">The parcels region specific local ID</param>
1255 /// <param name="type">the type of objects to return, <seealso cref="T:OpenMetaverse.ObjectReturnType"/></param>
1256 /// <param name="ownerIDs">A list containing object owners <seealso cref="OpenMetaverse.UUID"/>s to return</param>
1257 public void ReturnObjects(Simulator simulator, int localID, ObjectReturnType type, List<UUID> ownerIDs)
1258 {
1259 ParcelReturnObjectsPacket request = new ParcelReturnObjectsPacket();
1260 request.AgentData.AgentID = Client.Self.AgentID;
1261 request.AgentData.SessionID = Client.Self.SessionID;
1262  
1263 request.ParcelData.LocalID = localID;
1264 request.ParcelData.ReturnType = (uint)type;
1265  
1266 // A single null TaskID is (not) used for parcel object returns
1267 request.TaskIDs = new ParcelReturnObjectsPacket.TaskIDsBlock[1];
1268 request.TaskIDs[0] = new ParcelReturnObjectsPacket.TaskIDsBlock();
1269 request.TaskIDs[0].TaskID = UUID.Zero;
1270  
1271 // Convert the list of owner UUIDs to packet blocks if a list is given
1272 if (ownerIDs != null)
1273 {
1274 request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[ownerIDs.Count];
1275  
1276 for (int i = 0; i < ownerIDs.Count; i++)
1277 {
1278 request.OwnerIDs[i] = new ParcelReturnObjectsPacket.OwnerIDsBlock();
1279 request.OwnerIDs[i].OwnerID = ownerIDs[i];
1280 }
1281 }
1282 else
1283 {
1284 request.OwnerIDs = new ParcelReturnObjectsPacket.OwnerIDsBlock[0];
1285 }
1286  
1287 Client.Network.SendPacket(request, simulator);
1288 }
1289  
1290 /// <summary>
1291 /// Subdivide (split) a parcel
1292 /// </summary>
1293 /// <param name="simulator"></param>
1294 /// <param name="west"></param>
1295 /// <param name="south"></param>
1296 /// <param name="east"></param>
1297 /// <param name="north"></param>
1298 public void ParcelSubdivide(Simulator simulator, float west, float south, float east, float north)
1299 {
1300 ParcelDividePacket divide = new ParcelDividePacket();
1301 divide.AgentData.AgentID = Client.Self.AgentID;
1302 divide.AgentData.SessionID = Client.Self.SessionID;
1303 divide.ParcelData.East = east;
1304 divide.ParcelData.North = north;
1305 divide.ParcelData.South = south;
1306 divide.ParcelData.West = west;
1307  
1308 Client.Network.SendPacket(divide, simulator);
1309 }
1310  
1311 /// <summary>
1312 /// Join two parcels of land creating a single parcel
1313 /// </summary>
1314 /// <param name="simulator"></param>
1315 /// <param name="west"></param>
1316 /// <param name="south"></param>
1317 /// <param name="east"></param>
1318 /// <param name="north"></param>
1319 public void ParcelJoin(Simulator simulator, float west, float south, float east, float north)
1320 {
1321 ParcelJoinPacket join = new ParcelJoinPacket();
1322 join.AgentData.AgentID = Client.Self.AgentID;
1323 join.AgentData.SessionID = Client.Self.SessionID;
1324 join.ParcelData.East = east;
1325 join.ParcelData.North = north;
1326 join.ParcelData.South = south;
1327 join.ParcelData.West = west;
1328  
1329 Client.Network.SendPacket(join, simulator);
1330 }
1331  
1332 /// <summary>
1333 /// Get a parcels LocalID
1334 /// </summary>
1335 /// <param name="simulator">Simulator parcel is in</param>
1336 /// <param name="position">Vector3 position in simulator (Z not used)</param>
1337 /// <returns>0 on failure, or parcel LocalID on success.</returns>
1338 /// <remarks>A call to <code>Parcels.RequestAllSimParcels</code> is required to populate map and
1339 /// dictionary.</remarks>
1340 public int GetParcelLocalID(Simulator simulator, Vector3 position)
1341 {
1342 if (simulator.ParcelMap[(byte)position.Y / 4, (byte)position.X / 4] > 0)
1343 {
1344 return simulator.ParcelMap[(byte)position.Y / 4, (byte)position.X / 4];
1345 }
1346 else
1347 {
1348 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);
1349 return 0;
1350 }
1351 }
1352  
1353 /// <summary>
1354 /// Terraform (raise, lower, etc) an area or whole parcel of land
1355 /// </summary>
1356 /// <param name="simulator">Simulator land area is in.</param>
1357 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1358 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1359 /// <param name="brushSize">Size of area to modify</param>
1360 /// <returns>true on successful request sent.</returns>
1361 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1362 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1363 public bool Terraform(Simulator simulator, int localID, TerraformAction action, TerraformBrushSize brushSize)
1364 {
1365 return Terraform(simulator, localID, 0f, 0f, 0f, 0f, action, brushSize, 1);
1366 }
1367  
1368 /// <summary>
1369 /// Terraform (raise, lower, etc) an area or whole parcel of land
1370 /// </summary>
1371 /// <param name="simulator">Simulator land area is in.</param>
1372 /// <param name="west">west border of area to modify</param>
1373 /// <param name="south">south border of area to modify</param>
1374 /// <param name="east">east border of area to modify</param>
1375 /// <param name="north">north border of area to modify</param>
1376 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1377 /// <param name="brushSize">Size of area to modify</param>
1378 /// <returns>true on successful request sent.</returns>
1379 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1380 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1381 public bool Terraform(Simulator simulator, float west, float south, float east, float north,
1382 TerraformAction action, TerraformBrushSize brushSize)
1383 {
1384 return Terraform(simulator, -1, west, south, east, north, action, brushSize, 1);
1385 }
1386  
1387 /// <summary>
1388 /// Terraform (raise, lower, etc) an area or whole parcel of land
1389 /// </summary>
1390 /// <param name="simulator">Simulator land area is in.</param>
1391 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1392 /// <param name="west">west border of area to modify</param>
1393 /// <param name="south">south border of area to modify</param>
1394 /// <param name="east">east border of area to modify</param>
1395 /// <param name="north">north border of area to modify</param>
1396 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1397 /// <param name="brushSize">Size of area to modify</param>
1398 /// <param name="seconds">How many meters + or - to lower, 1 = 1 meter</param>
1399 /// <returns>true on successful request sent.</returns>
1400 /// <remarks>Settings.STORE_LAND_PATCHES must be true,
1401 /// Parcel information must be downloaded using <code>RequestAllSimParcels()</code></remarks>
1402 public bool Terraform(Simulator simulator, int localID, float west, float south, float east, float north,
1403 TerraformAction action, TerraformBrushSize brushSize, int seconds)
1404 {
1405 float height = 0f;
1406 int x, y;
1407 if (localID == -1)
1408 {
1409 x = (int)east - (int)west / 2;
1410 y = (int)north - (int)south / 2;
1411 }
1412 else
1413 {
1414 Parcel p;
1415 if (!simulator.Parcels.TryGetValue(localID, out p))
1416 {
1417 Logger.Log(String.Format("Can't find parcel {0} in simulator {1}", localID, simulator),
1418 Helpers.LogLevel.Warning, Client);
1419 return false;
1420 }
1421  
1422 x = (int)p.AABBMax.X - (int)p.AABBMin.X / 2;
1423 y = (int)p.AABBMax.Y - (int)p.AABBMin.Y / 2;
1424 }
1425  
1426 if (!simulator.TerrainHeightAtPoint(x, y, out height))
1427 {
1428 Logger.Log("Land Patch not stored for location", Helpers.LogLevel.Warning, Client);
1429 return false;
1430 }
1431  
1432 Terraform(simulator, localID, west, south, east, north, action, brushSize, seconds, height);
1433 return true;
1434 }
1435  
1436 /// <summary>
1437 /// Terraform (raise, lower, etc) an area or whole parcel of land
1438 /// </summary>
1439 /// <param name="simulator">Simulator land area is in.</param>
1440 /// <param name="localID">LocalID of parcel, or -1 if using bounding box</param>
1441 /// <param name="west">west border of area to modify</param>
1442 /// <param name="south">south border of area to modify</param>
1443 /// <param name="east">east border of area to modify</param>
1444 /// <param name="north">north border of area to modify</param>
1445 /// <param name="action">From Enum, Raise, Lower, Level, Smooth, Etc.</param>
1446 /// <param name="brushSize">Size of area to modify</param>
1447 /// <param name="seconds">How many meters + or - to lower, 1 = 1 meter</param>
1448 /// <param name="height">Height at which the terraform operation is acting at</param>
1449 public void Terraform(Simulator simulator, int localID, float west, float south, float east, float north,
1450 TerraformAction action, TerraformBrushSize brushSize, int seconds, float height)
1451 {
1452 ModifyLandPacket land = new ModifyLandPacket();
1453 land.AgentData.AgentID = Client.Self.AgentID;
1454 land.AgentData.SessionID = Client.Self.SessionID;
1455  
1456 land.ModifyBlock.Action = (byte)action;
1457 land.ModifyBlock.BrushSize = (byte)brushSize;
1458 land.ModifyBlock.Seconds = seconds;
1459 land.ModifyBlock.Height = height;
1460  
1461 land.ParcelData = new ModifyLandPacket.ParcelDataBlock[1];
1462 land.ParcelData[0] = new ModifyLandPacket.ParcelDataBlock();
1463 land.ParcelData[0].LocalID = localID;
1464 land.ParcelData[0].West = west;
1465 land.ParcelData[0].South = south;
1466 land.ParcelData[0].East = east;
1467 land.ParcelData[0].North = north;
1468  
1469 land.ModifyBlockExtended = new ModifyLandPacket.ModifyBlockExtendedBlock[1];
1470 land.ModifyBlockExtended[0] = new ModifyLandPacket.ModifyBlockExtendedBlock();
1471 land.ModifyBlockExtended[0].BrushSize = (float)brushSize;
1472  
1473 Client.Network.SendPacket(land, simulator);
1474 }
1475  
1476 /// <summary>
1477 /// Sends a request to the simulator to return a list of objects owned by specific owners
1478 /// </summary>
1479 /// <param name="localID">Simulator local ID of parcel</param>
1480 /// <param name="selectType">Owners, Others, Etc</param>
1481 /// <param name="ownerID">List containing keys of avatars objects to select;
1482 /// if List is null will return Objects of type <c>selectType</c></param>
1483 /// <remarks>Response data is returned in the event <seealso cref="E:ForceSelectObjectsReply"/></remarks>
1484 public void RequestSelectObjects(int localID, ObjectReturnType selectType, UUID ownerID)
1485 {
1486 ParcelSelectObjectsPacket select = new ParcelSelectObjectsPacket();
1487 select.AgentData.AgentID = Client.Self.AgentID;
1488 select.AgentData.SessionID = Client.Self.SessionID;
1489  
1490 select.ParcelData.LocalID = localID;
1491 select.ParcelData.ReturnType = (uint)selectType;
1492  
1493 select.ReturnIDs = new ParcelSelectObjectsPacket.ReturnIDsBlock[1];
1494 select.ReturnIDs[0] = new ParcelSelectObjectsPacket.ReturnIDsBlock();
1495 select.ReturnIDs[0].ReturnID = ownerID;
1496  
1497 Client.Network.SendPacket(select);
1498 }
1499  
1500 /// <summary>
1501 /// Eject and optionally ban a user from a parcel
1502 /// </summary>
1503 /// <param name="targetID">target key of avatar to eject</param>
1504 /// <param name="ban">true to also ban target</param>
1505 public void EjectUser(UUID targetID, bool ban)
1506 {
1507 EjectUserPacket eject = new EjectUserPacket();
1508 eject.AgentData.AgentID = Client.Self.AgentID;
1509 eject.AgentData.SessionID = Client.Self.SessionID;
1510 eject.Data.TargetID = targetID;
1511 if (ban) eject.Data.Flags = 1;
1512 else eject.Data.Flags = 0;
1513  
1514 Client.Network.SendPacket(eject);
1515 }
1516  
1517 /// <summary>
1518 /// Freeze or unfreeze an avatar over your land
1519 /// </summary>
1520 /// <param name="targetID">target key to freeze</param>
1521 /// <param name="freeze">true to freeze, false to unfreeze</param>
1522 public void FreezeUser(UUID targetID, bool freeze)
1523 {
1524 FreezeUserPacket frz = new FreezeUserPacket();
1525 frz.AgentData.AgentID = Client.Self.AgentID;
1526 frz.AgentData.SessionID = Client.Self.SessionID;
1527 frz.Data.TargetID = targetID;
1528 if (freeze) frz.Data.Flags = 0;
1529 else frz.Data.Flags = 1;
1530  
1531 Client.Network.SendPacket(frz);
1532 }
1533  
1534 /// <summary>
1535 /// Abandon a parcel of land
1536 /// </summary>
1537 /// <param name="simulator">Simulator parcel is in</param>
1538 /// <param name="localID">Simulator local ID of parcel</param>
1539 public void ReleaseParcel(Simulator simulator, int localID)
1540 {
1541 ParcelReleasePacket abandon = new ParcelReleasePacket();
1542 abandon.AgentData.AgentID = Client.Self.AgentID;
1543 abandon.AgentData.SessionID = Client.Self.SessionID;
1544 abandon.Data.LocalID = localID;
1545  
1546 Client.Network.SendPacket(abandon, simulator);
1547 }
1548  
1549 /// <summary>
1550 /// Requests the UUID of the parcel in a remote region at a specified location
1551 /// </summary>
1552 /// <param name="location">Location of the parcel in the remote region</param>
1553 /// <param name="regionHandle">Remote region handle</param>
1554 /// <param name="regionID">Remote region UUID</param>
1555 /// <returns>If successful UUID of the remote parcel, UUID.Zero otherwise</returns>
1556 public UUID RequestRemoteParcelID(Vector3 location, ulong regionHandle, UUID regionID)
1557 {
1558 if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null)
1559 return UUID.Zero;
1560  
1561 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("RemoteParcelRequest");
1562  
1563 if (url != null)
1564 {
1565 RemoteParcelRequestRequest msg = new RemoteParcelRequestRequest();
1566 msg.Location = location;
1567 msg.RegionHandle = regionHandle;
1568 msg.RegionID = regionID;
1569  
1570 try
1571 {
1572 CapsClient request = new CapsClient(url);
1573 OSD result = request.GetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1574 RemoteParcelRequestReply response = new RemoteParcelRequestReply();
1575 response.Deserialize((OSDMap)result);
1576 return response.ParcelID;
1577 }
1578 catch (Exception)
1579 {
1580 Logger.Log("Failed to fetch remote parcel ID", Helpers.LogLevel.Debug, Client);
1581 }
1582 }
1583  
1584 return UUID.Zero;
1585  
1586 }
1587  
1588 /// <summary>
1589 /// Retrieves information on resources used by the parcel
1590 /// </summary>
1591 /// <param name="parcelID">UUID of the parcel</param>
1592 /// <param name="getDetails">Should per object resource usage be requested</param>
1593 /// <param name="callback">Callback invoked when the request is complete</param>
1594 public void GetParcelResouces(UUID parcelID, bool getDetails, LandResourcesCallback callback)
1595 {
1596 try
1597 {
1598 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("LandResources");
1599 CapsClient request = new CapsClient(url);
1600  
1601 request.OnComplete += delegate(CapsClient client, OSD result, Exception error)
1602 {
1603 try
1604 {
1605 if (result == null || error != null)
1606 {
1607 callback(false, null);
1608 }
1609 LandResourcesMessage response = new LandResourcesMessage();
1610 response.Deserialize((OSDMap)result);
1611  
1612 CapsClient summaryRequest = new CapsClient(response.ScriptResourceSummary);
1613 OSD summaryResponse = summaryRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
1614  
1615 LandResourcesInfo res = new LandResourcesInfo();
1616 res.Deserialize((OSDMap)summaryResponse);
1617  
1618 if (response.ScriptResourceDetails != null && getDetails)
1619 {
1620 CapsClient detailRequest = new CapsClient(response.ScriptResourceDetails);
1621 OSD detailResponse = detailRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
1622 res.Deserialize((OSDMap)detailResponse);
1623 }
1624 callback(true, res);
1625 }
1626 catch (Exception ex)
1627 {
1628 Logger.Log("Failed fetching land resources", Helpers.LogLevel.Error, Client, ex);
1629 callback(false, null);
1630 }
1631 };
1632  
1633 LandResourcesRequest param = new LandResourcesRequest();
1634 param.ParcelID = parcelID;
1635 request.BeginGetResponse(param.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
1636  
1637 }
1638 catch (Exception ex)
1639 {
1640 Logger.Log("Failed fetching land resources:", Helpers.LogLevel.Error, Client, ex);
1641 callback(false, null);
1642 }
1643 }
1644  
1645 #endregion Public Methods
1646  
1647 #region Packet Handlers
1648  
1649 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1650 /// <param name="sender">The sender</param>
1651 /// <param name="e">The EventArgs object containing the packet data</param>
1652 /// <remarks>Raises the <see cref="ParcelDwellReply"/> event</remarks>
1653 protected void ParcelDwellReplyHandler(object sender, PacketReceivedEventArgs e)
1654 {
1655 if (m_DwellReply != null || Client.Settings.ALWAYS_REQUEST_PARCEL_DWELL == true)
1656 {
1657 Packet packet = e.Packet;
1658 Simulator simulator = e.Simulator;
1659  
1660 ParcelDwellReplyPacket dwell = (ParcelDwellReplyPacket)packet;
1661  
1662 lock (simulator.Parcels.Dictionary)
1663 {
1664 if (simulator.Parcels.Dictionary.ContainsKey(dwell.Data.LocalID))
1665 {
1666 Parcel parcel = simulator.Parcels.Dictionary[dwell.Data.LocalID];
1667 parcel.Dwell = dwell.Data.Dwell;
1668 simulator.Parcels.Dictionary[dwell.Data.LocalID] = parcel;
1669 }
1670 }
1671  
1672 if (m_DwellReply != null)
1673 {
1674 OnParcelDwellReply(new ParcelDwellReplyEventArgs(dwell.Data.ParcelID, dwell.Data.LocalID, dwell.Data.Dwell));
1675 }
1676 }
1677 }
1678  
1679 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1680 /// <param name="sender">The sender</param>
1681 /// <param name="e">The EventArgs object containing the packet data</param>
1682 /// <remarks>Raises the <see cref="ParcelInfoReply"/> event</remarks>
1683 protected void ParcelInfoReplyHandler(object sender, PacketReceivedEventArgs e)
1684 {
1685 if (m_ParcelInfo != null)
1686 {
1687 Packet packet = e.Packet;
1688 ParcelInfoReplyPacket info = (ParcelInfoReplyPacket)packet;
1689  
1690 ParcelInfo parcelInfo = new ParcelInfo();
1691  
1692 parcelInfo.ActualArea = info.Data.ActualArea;
1693 parcelInfo.AuctionID = info.Data.AuctionID;
1694 parcelInfo.BillableArea = info.Data.BillableArea;
1695 parcelInfo.Description = Utils.BytesToString(info.Data.Desc);
1696 parcelInfo.Dwell = info.Data.Dwell;
1697 parcelInfo.GlobalX = info.Data.GlobalX;
1698 parcelInfo.GlobalY = info.Data.GlobalY;
1699 parcelInfo.GlobalZ = info.Data.GlobalZ;
1700 parcelInfo.ID = info.Data.ParcelID;
1701 parcelInfo.Mature = ((info.Data.Flags & 1) != 0) ? true : false;
1702 parcelInfo.Name = Utils.BytesToString(info.Data.Name);
1703 parcelInfo.OwnerID = info.Data.OwnerID;
1704 parcelInfo.SalePrice = info.Data.SalePrice;
1705 parcelInfo.SimName = Utils.BytesToString(info.Data.SimName);
1706 parcelInfo.SnapshotID = info.Data.SnapshotID;
1707  
1708 OnParcelInfoReply(new ParcelInfoReplyEventArgs(parcelInfo));
1709 }
1710 }
1711  
1712 protected void ParcelPropertiesReplyHandler(string capsKey, IMessage message, Simulator simulator)
1713 {
1714 if (m_ParcelProperties != null || Client.Settings.PARCEL_TRACKING == true)
1715 {
1716 ParcelPropertiesMessage msg = (ParcelPropertiesMessage)message;
1717  
1718 Parcel parcel = new Parcel(msg.LocalID);
1719  
1720 parcel.AABBMax = msg.AABBMax;
1721 parcel.AABBMin = msg.AABBMin;
1722 parcel.Area = msg.Area;
1723 parcel.AuctionID = msg.AuctionID;
1724 parcel.AuthBuyerID = msg.AuthBuyerID;
1725 parcel.Bitmap = msg.Bitmap;
1726 parcel.Category = msg.Category;
1727 parcel.ClaimDate = msg.ClaimDate;
1728 parcel.ClaimPrice = msg.ClaimPrice;
1729 parcel.Desc = msg.Desc;
1730 parcel.Flags = msg.ParcelFlags;
1731 parcel.GroupID = msg.GroupID;
1732 parcel.GroupPrims = msg.GroupPrims;
1733 parcel.IsGroupOwned = msg.IsGroupOwned;
1734 parcel.Landing = msg.LandingType;
1735 parcel.MaxPrims = msg.MaxPrims;
1736 parcel.Media.MediaAutoScale = msg.MediaAutoScale;
1737 parcel.Media.MediaID = msg.MediaID;
1738 parcel.Media.MediaURL = msg.MediaURL;
1739 parcel.MusicURL = msg.MusicURL;
1740 parcel.Name = msg.Name;
1741 parcel.OtherCleanTime = msg.OtherCleanTime;
1742 parcel.OtherCount = msg.OtherCount;
1743 parcel.OtherPrims = msg.OtherPrims;
1744 parcel.OwnerID = msg.OwnerID;
1745 parcel.OwnerPrims = msg.OwnerPrims;
1746 parcel.ParcelPrimBonus = msg.ParcelPrimBonus;
1747 parcel.PassHours = msg.PassHours;
1748 parcel.PassPrice = msg.PassPrice;
1749 parcel.PublicCount = msg.PublicCount;
1750 parcel.RegionDenyAgeUnverified = msg.RegionDenyAgeUnverified;
1751 parcel.RegionDenyAnonymous = msg.RegionDenyAnonymous;
1752 parcel.RegionPushOverride = msg.RegionPushOverride;
1753 parcel.RentPrice = msg.RentPrice;
1754 ParcelResult result = msg.RequestResult;
1755 parcel.SalePrice = msg.SalePrice;
1756 int selectedPrims = msg.SelectedPrims;
1757 parcel.SelfCount = msg.SelfCount;
1758 int sequenceID = msg.SequenceID;
1759 parcel.SimWideMaxPrims = msg.SimWideMaxPrims;
1760 parcel.SimWideTotalPrims = msg.SimWideTotalPrims;
1761 bool snapSelection = msg.SnapSelection;
1762 parcel.SnapshotID = msg.SnapshotID;
1763 parcel.Status = msg.Status;
1764 parcel.TotalPrims = msg.TotalPrims;
1765 parcel.UserLocation = msg.UserLocation;
1766 parcel.UserLookAt = msg.UserLookAt;
1767 parcel.Media.MediaDesc = msg.MediaDesc;
1768 parcel.Media.MediaHeight = msg.MediaHeight;
1769 parcel.Media.MediaWidth = msg.MediaWidth;
1770 parcel.Media.MediaLoop = msg.MediaLoop;
1771 parcel.Media.MediaType = msg.MediaType;
1772 parcel.ObscureMedia = msg.ObscureMedia;
1773 parcel.ObscureMusic = msg.ObscureMusic;
16 eva 1774 parcel.SeeAVs = msg.SeeAVs;
1775 parcel.AnyAVSounds = msg.AnyAVSounds;
1776 parcel.GroupAVSounds = msg.GroupAVSounds;
1 vero 1777  
1778 if (Client.Settings.PARCEL_TRACKING)
1779 {
1780 lock (simulator.Parcels.Dictionary)
1781 simulator.Parcels.Dictionary[parcel.LocalID] = parcel;
1782  
1783 bool set = false;
1784 int y, x, index, bit;
1785 for (y = 0; y < 64; y++)
1786 {
1787 for (x = 0; x < 64; x++)
1788 {
1789 index = (y * 64) + x;
1790 bit = index % 8;
1791 index >>= 3;
1792  
1793 if ((parcel.Bitmap[index] & (1 << bit)) != 0)
1794 {
1795 simulator.ParcelMap[y, x] = parcel.LocalID;
1796 set = true;
1797 }
1798 }
1799 }
1800  
1801 if (!set)
1802 {
1803 Logger.Log("Received a parcel with a bitmap that did not map to any locations",
1804 Helpers.LogLevel.Warning);
1805 }
1806 }
1807  
1808 if (sequenceID.Equals(int.MaxValue) && WaitForSimParcel != null)
1809 WaitForSimParcel.Set();
1810  
1811 // auto request acl, will be stored in parcel tracking dictionary if enabled
1812 if (Client.Settings.ALWAYS_REQUEST_PARCEL_ACL)
1813 Client.Parcels.RequestParcelAccessList(simulator, parcel.LocalID,
1814 AccessList.Both, sequenceID);
1815  
1816 // auto request dwell, will be stored in parcel tracking dictionary if enables
1817 if (Client.Settings.ALWAYS_REQUEST_PARCEL_DWELL)
1818 Client.Parcels.RequestDwell(simulator, parcel.LocalID);
1819  
1820 // Fire the callback for parcel properties being received
1821 if (m_ParcelProperties != null)
1822 {
1823 OnParcelProperties(new ParcelPropertiesEventArgs(simulator, parcel, result, selectedPrims, sequenceID, snapSelection));
1824 }
1825  
1826 // Check if all of the simulator parcels have been retrieved, if so fire another callback
1827 if (simulator.IsParcelMapFull() && m_SimParcelsDownloaded != null)
1828 {
1829 OnSimParcelsDownloaded(new SimParcelsDownloadedEventArgs(simulator, simulator.Parcels, simulator.ParcelMap));
1830 }
1831 }
1832 }
1833  
1834 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1835 /// <param name="sender">The sender</param>
1836 /// <param name="e">The EventArgs object containing the packet data</param>
1837 /// <remarks>Raises the <see cref="ParcelAccessListReply"/> event</remarks>
1838 protected void ParcelAccessListReplyHandler(object sender, PacketReceivedEventArgs e)
1839 {
1840 if (m_ParcelACL != null || Client.Settings.ALWAYS_REQUEST_PARCEL_ACL == true)
1841 {
1842 Packet packet = e.Packet;
1843 Simulator simulator = e.Simulator;
1844  
1845 ParcelAccessListReplyPacket reply = (ParcelAccessListReplyPacket)packet;
1846  
1847 List<ParcelAccessEntry> accessList = new List<ParcelAccessEntry>(reply.List.Length);
1848  
1849 for (int i = 0; i < reply.List.Length; i++)
1850 {
1851 ParcelAccessEntry pae = new ParcelAccessEntry();
1852 pae.AgentID = reply.List[i].ID;
1853 pae.Time = Utils.UnixTimeToDateTime((uint)reply.List[i].Time);
1854 pae.Flags = (AccessList)reply.List[i].Flags;
1855  
1856 accessList.Add(pae);
1857 }
1858  
1859 lock (simulator.Parcels.Dictionary)
1860 {
1861 if (simulator.Parcels.Dictionary.ContainsKey(reply.Data.LocalID))
1862 {
1863 Parcel parcel = simulator.Parcels.Dictionary[reply.Data.LocalID];
1864 if ((AccessList)reply.Data.Flags == AccessList.Ban)
1865 parcel.AccessBlackList = accessList;
1866 else
1867 parcel.AccessWhiteList = accessList;
1868  
1869 simulator.Parcels.Dictionary[reply.Data.LocalID] = parcel;
1870 }
1871 }
1872  
1873  
1874 if (m_ParcelACL != null)
1875 {
1876 OnParcelAccessListReply(new ParcelAccessListReplyEventArgs(simulator, reply.Data.SequenceID, reply.Data.LocalID,
1877 reply.Data.Flags, accessList));
1878 }
1879 }
1880 }
1881  
1882 protected void ParcelObjectOwnersReplyHandler(string capsKey, IMessage message, Simulator simulator)
1883 {
1884 if (m_ParcelObjectOwnersReply != null)
1885 {
1886 List<ParcelPrimOwners> primOwners = new List<ParcelPrimOwners>();
1887  
1888 ParcelObjectOwnersReplyMessage msg = (ParcelObjectOwnersReplyMessage)message;
1889  
1890 for (int i = 0; i < msg.PrimOwnersBlock.Length; i++)
1891 {
1892 ParcelPrimOwners primOwner = new ParcelPrimOwners();
1893 primOwner.OwnerID = msg.PrimOwnersBlock[i].OwnerID;
1894 primOwner.Count = msg.PrimOwnersBlock[i].Count;
1895 primOwner.IsGroupOwned = msg.PrimOwnersBlock[i].IsGroupOwned;
1896 primOwner.OnlineStatus = msg.PrimOwnersBlock[i].OnlineStatus;
1897 primOwner.NewestPrim = msg.PrimOwnersBlock[i].TimeStamp;
1898  
1899 primOwners.Add(primOwner);
1900 }
1901  
1902 OnParcelObjectOwnersReply(new ParcelObjectOwnersReplyEventArgs(simulator, primOwners));
1903 }
1904 }
1905  
1906 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1907 /// <param name="sender">The sender</param>
1908 /// <param name="e">The EventArgs object containing the packet data</param>
1909 /// <remarks>Raises the <see cref="ForceSelectObjectsReply"/> event</remarks>
1910 protected void SelectParcelObjectsReplyHandler(object sender, PacketReceivedEventArgs e)
1911 {
1912 if (m_ForceSelectObjects != null)
1913 {
1914 Packet packet = e.Packet;
1915 Simulator simulator = e.Simulator;
1916  
1917 ForceObjectSelectPacket reply = (ForceObjectSelectPacket)packet;
1918 List<uint> objectIDs = new List<uint>(reply.Data.Length);
1919  
1920 for (int i = 0; i < reply.Data.Length; i++)
1921 {
1922 objectIDs.Add(reply.Data[i].LocalID);
1923 }
1924  
1925 OnForceSelectObjectsReply(new ForceSelectObjectsReplyEventArgs(simulator, objectIDs, reply._Header.ResetList));
1926 }
1927 }
1928  
1929 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1930 /// <param name="sender">The sender</param>
1931 /// <param name="e">The EventArgs object containing the packet data</param>
1932 /// <remarks>Raises the <see cref="ParcelMediaUpdateReply"/> event</remarks>
1933 protected void ParcelMediaUpdateHandler(object sender, PacketReceivedEventArgs e)
1934 {
1935 if (m_ParcelMediaUpdateReply != null)
1936 {
1937 Packet packet = e.Packet;
1938 Simulator simulator = e.Simulator;
1939  
1940 ParcelMediaUpdatePacket reply = (ParcelMediaUpdatePacket)packet;
1941 ParcelMedia media = new ParcelMedia();
1942  
1943 media.MediaAutoScale = (reply.DataBlock.MediaAutoScale == (byte)0x1) ? true : false;
1944 media.MediaID = reply.DataBlock.MediaID;
1945 media.MediaDesc = Utils.BytesToString(reply.DataBlockExtended.MediaDesc);
1946 media.MediaHeight = reply.DataBlockExtended.MediaHeight;
1947 media.MediaLoop = ((reply.DataBlockExtended.MediaLoop & 1) != 0) ? true : false;
1948 media.MediaType = Utils.BytesToString(reply.DataBlockExtended.MediaType);
1949 media.MediaWidth = reply.DataBlockExtended.MediaWidth;
1950 media.MediaURL = Utils.BytesToString(reply.DataBlock.MediaURL);
1951  
1952 OnParcelMediaUpdateReply(new ParcelMediaUpdateReplyEventArgs(simulator, media));
1953 }
1954 }
1955  
1956 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1957 /// <param name="sender">The sender</param>
1958 /// <param name="e">The EventArgs object containing the packet data</param>
1959 protected void ParcelOverlayHandler(object sender, PacketReceivedEventArgs e)
1960 {
1961 const int OVERLAY_COUNT = 4;
1962 Packet packet = e.Packet;
1963 Simulator simulator = e.Simulator;
1964  
1965 ParcelOverlayPacket overlay = (ParcelOverlayPacket)packet;
1966  
1967 if (overlay.ParcelData.SequenceID >= 0 && overlay.ParcelData.SequenceID < OVERLAY_COUNT)
1968 {
1969 int length = overlay.ParcelData.Data.Length;
1970  
1971 Buffer.BlockCopy(overlay.ParcelData.Data, 0, simulator.ParcelOverlay,
1972 overlay.ParcelData.SequenceID * length, length);
1973 simulator.ParcelOverlaysReceived++;
1974  
1975 if (simulator.ParcelOverlaysReceived >= OVERLAY_COUNT)
1976 {
1977 // TODO: ParcelOverlaysReceived should become internal, and reset to zero every
1978 // time it hits four. Also need a callback here
1979 }
1980 }
1981 else
1982 {
1983 Logger.Log("Parcel overlay with sequence ID of " + overlay.ParcelData.SequenceID +
1984 " received from " + simulator.ToString(), Helpers.LogLevel.Warning, Client);
1985 }
1986 }
1987  
1988 /// <summary>Process an incoming packet and raise the appropriate events</summary>
1989 /// <param name="sender">The sender</param>
1990 /// <param name="e">The EventArgs object containing the packet data</param>
1991 /// <remarks>Raises the <see cref="ParcelMediaCommand"/> event</remarks>
1992 protected void ParcelMediaCommandMessagePacketHandler(object sender, PacketReceivedEventArgs e)
1993 {
1994 if (m_ParcelMediaCommand != null)
1995 {
1996 Packet packet = e.Packet;
1997 Simulator simulator = e.Simulator;
1998  
1999 ParcelMediaCommandMessagePacket pmc = (ParcelMediaCommandMessagePacket)packet;
2000 ParcelMediaCommandMessagePacket.CommandBlockBlock block = pmc.CommandBlock;
2001  
2002 OnParcelMediaCommand(new ParcelMediaCommandEventArgs(simulator, pmc.Header.Sequence, (ParcelFlags)block.Flags,
2003 (ParcelMediaCommand)block.Command, block.Time));
2004 }
2005 }
2006  
2007 #endregion Packet Handlers
2008 }
2009 #region EventArgs classes
2010  
2011 /// <summary>Contains a parcels dwell data returned from the simulator in response to an <see cref="RequestParcelDwell"/></summary>
2012 public class ParcelDwellReplyEventArgs : EventArgs
2013 {
2014 private readonly UUID m_ParcelID;
2015 private readonly int m_LocalID;
2016 private readonly float m_Dwell;
2017  
2018 /// <summary>Get the global ID of the parcel</summary>
2019 public UUID ParcelID { get { return m_ParcelID; } }
2020 /// <summary>Get the simulator specific ID of the parcel</summary>
2021 public int LocalID { get { return m_LocalID; } }
2022 /// <summary>Get the calculated dwell</summary>
2023 public float Dwell { get { return m_Dwell; } }
2024  
2025 /// <summary>
2026 /// Construct a new instance of the ParcelDwellReplyEventArgs class
2027 /// </summary>
2028 /// <param name="parcelID">The global ID of the parcel</param>
2029 /// <param name="localID">The simulator specific ID of the parcel</param>
2030 /// <param name="dwell">The calculated dwell for the parcel</param>
2031 public ParcelDwellReplyEventArgs(UUID parcelID, int localID, float dwell)
2032 {
2033 this.m_ParcelID = parcelID;
2034 this.m_LocalID = localID;
2035 this.m_Dwell = dwell;
2036 }
2037 }
2038  
2039 /// <summary>Contains basic parcel information data returned from the
2040 /// simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
2041 public class ParcelInfoReplyEventArgs : EventArgs
2042 {
2043 private readonly ParcelInfo m_Parcel;
2044  
2045 /// <summary>Get the <see cref="ParcelInfo"/> object containing basic parcel info</summary>
2046 public ParcelInfo Parcel { get { return m_Parcel; } }
2047  
2048 /// <summary>
2049 /// Construct a new instance of the ParcelInfoReplyEventArgs class
2050 /// </summary>
2051 /// <param name="parcel">The <see cref="ParcelInfo"/> object containing basic parcel info</param>
2052 public ParcelInfoReplyEventArgs(ParcelInfo parcel)
2053 {
2054 this.m_Parcel = parcel;
2055 }
2056 }
2057  
2058 /// <summary>Contains basic parcel information data returned from the simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
2059 public class ParcelPropertiesEventArgs : EventArgs
2060 {
2061 private readonly Simulator m_Simulator;
2062 private Parcel m_Parcel;
2063 private readonly ParcelResult m_Result;
2064 private readonly int m_SelectedPrims;
2065 private readonly int m_SequenceID;
2066 private readonly bool m_SnapSelection;
2067  
2068 /// <summary>Get the simulator the parcel is located in</summary>
2069 public Simulator Simulator { get { return m_Simulator; } }
2070 /// <summary>Get the <see cref="Parcel"/> object containing the details</summary>
2071 /// <remarks>If Result is NoData, this object will not contain valid data</remarks>
2072 public Parcel Parcel { get { return m_Parcel; } }
2073 /// <summary>Get the result of the request</summary>
2074 public ParcelResult Result { get { return m_Result; } }
2075 /// <summary>Get the number of primitieves your agent is
2076 /// currently selecting and or sitting on in this parcel</summary>
2077 public int SelectedPrims { get { return m_SelectedPrims; } }
2078 /// <summary>Get the user assigned ID used to correlate a request with
2079 /// these results</summary>
2080 public int SequenceID { get { return m_SequenceID; } }
2081 /// <summary>TODO:</summary>
2082 public bool SnapSelection { get { return m_SnapSelection; } }
2083  
2084 /// <summary>
2085 /// Construct a new instance of the ParcelPropertiesEventArgs class
2086 /// </summary>
2087 /// <param name="simulator">The <see cref="Parcel"/> object containing the details</param>
2088 /// <param name="parcel">The <see cref="Parcel"/> object containing the details</param>
2089 /// <param name="result">The result of the request</param>
2090 /// <param name="selectedPrims">The number of primitieves your agent is
2091 /// currently selecting and or sitting on in this parcel</param>
2092 /// <param name="sequenceID">The user assigned ID used to correlate a request with
2093 /// these results</param>
2094 /// <param name="snapSelection">TODO:</param>
2095 public ParcelPropertiesEventArgs(Simulator simulator, Parcel parcel, ParcelResult result, int selectedPrims,
2096 int sequenceID, bool snapSelection)
2097 {
2098 this.m_Simulator = simulator;
2099 this.m_Parcel = parcel;
2100 this.m_Result = result;
2101 this.m_SelectedPrims = selectedPrims;
2102 this.m_SequenceID = sequenceID;
2103 this.m_SnapSelection = snapSelection;
2104 }
2105 }
2106  
2107 /// <summary>Contains blacklist and whitelist data returned from the simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
2108 public class ParcelAccessListReplyEventArgs : EventArgs
2109 {
2110 private readonly Simulator m_Simulator;
2111 private readonly int m_SequenceID;
2112 private readonly int m_LocalID;
2113 private readonly uint m_Flags;
2114 private readonly List<ParcelManager.ParcelAccessEntry> m_AccessList;
2115  
2116 /// <summary>Get the simulator the parcel is located in</summary>
2117 public Simulator Simulator { get { return m_Simulator; } }
2118 /// <summary>Get the user assigned ID used to correlate a request with
2119 /// these results</summary>
2120 public int SequenceID { get { return m_SequenceID; } }
2121 /// <summary>Get the simulator specific ID of the parcel</summary>
2122 public int LocalID { get { return m_LocalID; } }
2123 /// <summary>TODO:</summary>
2124 public uint Flags { get { return m_Flags; } }
2125 /// <summary>Get the list containing the white/blacklisted agents for the parcel</summary>
2126 public List<ParcelManager.ParcelAccessEntry> AccessList { get { return m_AccessList; } }
2127  
2128 /// <summary>
2129 /// Construct a new instance of the ParcelAccessListReplyEventArgs class
2130 /// </summary>
2131 /// <param name="simulator">The simulator the parcel is located in</param>
2132 /// <param name="sequenceID">The user assigned ID used to correlate a request with
2133 /// these results</param>
2134 /// <param name="localID">The simulator specific ID of the parcel</param>
2135 /// <param name="flags">TODO:</param>
2136 /// <param name="accessEntries">The list containing the white/blacklisted agents for the parcel</param>
2137 public ParcelAccessListReplyEventArgs(Simulator simulator, int sequenceID, int localID, uint flags, List<ParcelManager.ParcelAccessEntry> accessEntries)
2138 {
2139 this.m_Simulator = simulator;
2140 this.m_SequenceID = sequenceID;
2141 this.m_LocalID = localID;
2142 this.m_Flags = flags;
2143 this.m_AccessList = accessEntries;
2144 }
2145 }
2146  
2147 /// <summary>Contains blacklist and whitelist data returned from the
2148 /// simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
2149 public class ParcelObjectOwnersReplyEventArgs : EventArgs
2150 {
2151 private readonly Simulator m_Simulator;
2152 private readonly List<ParcelManager.ParcelPrimOwners> m_Owners;
2153  
2154 /// <summary>Get the simulator the parcel is located in</summary>
2155 public Simulator Simulator { get { return m_Simulator; } }
2156 /// <summary>Get the list containing prim ownership counts</summary>
2157 public List<ParcelManager.ParcelPrimOwners> PrimOwners { get { return m_Owners; } }
2158  
2159 /// <summary>
2160 /// Construct a new instance of the ParcelObjectOwnersReplyEventArgs class
2161 /// </summary>
2162 /// <param name="simulator">The simulator the parcel is located in</param>
2163 /// <param name="primOwners">The list containing prim ownership counts</param>
2164 public ParcelObjectOwnersReplyEventArgs(Simulator simulator, List<ParcelManager.ParcelPrimOwners> primOwners)
2165 {
2166 this.m_Simulator = simulator;
2167 this.m_Owners = primOwners;
2168 }
2169 }
2170  
2171 /// <summary>Contains the data returned when all parcel data has been retrieved from a simulator</summary>
2172 public class SimParcelsDownloadedEventArgs : EventArgs
2173 {
2174 private readonly Simulator m_Simulator;
2175 private readonly InternalDictionary<int, Parcel> m_Parcels;
2176 private readonly int[,] m_ParcelMap;
2177  
2178 /// <summary>Get the simulator the parcel data was retrieved from</summary>
2179 public Simulator Simulator { get { return m_Simulator; } }
2180 /// <summary>A dictionary containing the parcel data where the key correlates to the ParcelMap entry</summary>
2181 public InternalDictionary<int, Parcel> Parcels { get { return m_Parcels; } }
2182 /// <summary>Get the multidimensional array containing a x,y grid mapped
2183 /// to each 64x64 parcel's LocalID.</summary>
2184 public int[,] ParcelMap { get { return m_ParcelMap; } }
2185  
2186 /// <summary>
2187 /// Construct a new instance of the SimParcelsDownloadedEventArgs class
2188 /// </summary>
2189 /// <param name="simulator">The simulator the parcel data was retrieved from</param>
2190 /// <param name="simParcels">The dictionary containing the parcel data</param>
2191 /// <param name="parcelMap">The multidimensional array containing a x,y grid mapped
2192 /// to each 64x64 parcel's LocalID.</param>
2193 public SimParcelsDownloadedEventArgs(Simulator simulator, InternalDictionary<int, Parcel> simParcels, int[,] parcelMap)
2194 {
2195 this.m_Simulator = simulator;
2196 this.m_Parcels = simParcels;
2197 this.m_ParcelMap = parcelMap;
2198 }
2199 }
2200  
2201 /// <summary>Contains the data returned when a <see cref="RequestForceSelectObjects"/> request</summary>
2202 public class ForceSelectObjectsReplyEventArgs : EventArgs
2203 {
2204 private readonly Simulator m_Simulator;
2205 private readonly List<uint> m_ObjectIDs;
2206 private readonly bool m_ResetList;
2207  
2208 /// <summary>Get the simulator the parcel data was retrieved from</summary>
2209 public Simulator Simulator { get { return m_Simulator; } }
2210 /// <summary>Get the list of primitive IDs</summary>
2211 public List<uint> ObjectIDs { get { return m_ObjectIDs; } }
2212 /// <summary>true if the list is clean and contains the information
2213 /// only for a given request</summary>
2214 public bool ResetList { get { return m_ResetList; } }
2215  
2216 /// <summary>
2217 /// Construct a new instance of the ForceSelectObjectsReplyEventArgs class
2218 /// </summary>
2219 /// <param name="simulator">The simulator the parcel data was retrieved from</param>
2220 /// <param name="objectIDs">The list of primitive IDs</param>
2221 /// <param name="resetList">true if the list is clean and contains the information
2222 /// only for a given request</param>
2223 public ForceSelectObjectsReplyEventArgs(Simulator simulator, List<uint> objectIDs, bool resetList)
2224 {
2225 this.m_Simulator = simulator;
2226 this.m_ObjectIDs = objectIDs;
2227 this.m_ResetList = resetList;
2228 }
2229 }
2230  
2231 /// <summary>Contains data when the media data for a parcel the avatar is on changes</summary>
2232 public class ParcelMediaUpdateReplyEventArgs : EventArgs
2233 {
2234 private readonly Simulator m_Simulator;
2235 private readonly ParcelMedia m_ParcelMedia;
2236  
2237 /// <summary>Get the simulator the parcel media data was updated in</summary>
2238 public Simulator Simulator { get { return m_Simulator; } }
2239 /// <summary>Get the updated media information</summary>
2240 public ParcelMedia Media { get { return m_ParcelMedia; } }
2241  
2242 /// <summary>
2243 /// Construct a new instance of the ParcelMediaUpdateReplyEventArgs class
2244 /// </summary>
2245 /// <param name="simulator">the simulator the parcel media data was updated in</param>
2246 /// <param name="media">The updated media information</param>
2247 public ParcelMediaUpdateReplyEventArgs(Simulator simulator, ParcelMedia media)
2248 {
2249 this.m_Simulator = simulator;
2250 this.m_ParcelMedia = media;
2251 }
2252 }
2253  
2254 /// <summary>Contains the media command for a parcel the agent is currently on</summary>
2255 public class ParcelMediaCommandEventArgs : EventArgs
2256 {
2257 private readonly Simulator m_Simulator;
2258 private readonly uint m_Sequence;
2259 private readonly ParcelFlags m_ParcelFlags;
2260 private readonly ParcelMediaCommand m_MediaCommand;
2261 private readonly float m_Time;
2262  
2263 /// <summary>Get the simulator the parcel media command was issued in</summary>
2264 public Simulator Simulator { get { return m_Simulator; } }
2265 /// <summary></summary>
2266 public uint Sequence { get { return m_Sequence; } }
2267 /// <summary></summary>
2268 public ParcelFlags ParcelFlags { get { return m_ParcelFlags; } }
2269 /// <summary>Get the media command that was sent</summary>
2270 public ParcelMediaCommand MediaCommand { get { return m_MediaCommand; } }
2271 /// <summary></summary>
2272 public float Time { get { return m_Time; } }
2273  
2274 /// <summary>
2275 /// Construct a new instance of the ParcelMediaCommandEventArgs class
2276 /// </summary>
2277 /// <param name="simulator">The simulator the parcel media command was issued in</param>
2278 /// <param name="sequence"></param>
2279 /// <param name="flags"></param>
2280 /// <param name="command">The media command that was sent</param>
2281 /// <param name="time"></param>
2282 public ParcelMediaCommandEventArgs(Simulator simulator, uint sequence, ParcelFlags flags, ParcelMediaCommand command, float time)
2283 {
2284 this.m_Simulator = simulator;
2285 this.m_Sequence = sequence;
2286 this.m_ParcelFlags = flags;
2287 this.m_MediaCommand = command;
2288 this.m_Time = time;
2289 }
2290 }
2291 #endregion
2292 }