PageRenderTime 65ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenMetaverse/Modules/ParcelManager.cs

https://bitbucket.org/VirtualReality/3rdparty-addon-modules
C# | 2280 lines | 1293 code | 246 blank | 741 comment | 111 complexity | ade307e822a96a4cedda2b1a4e5d7e63 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2007-2009, 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. using System;
  27. using System.Threading;
  28. using System.Reflection;
  29. using System.Collections.Generic;
  30. using OpenMetaverse.Http;
  31. using OpenMetaverse.Packets;
  32. using OpenMetaverse.Interfaces;
  33. using OpenMetaverse.StructuredData;
  34. using OpenMetaverse.Messages.Linden;
  35. namespace OpenMetaverse
  36. {
  37. #region Enums
  38. /// <summary>
  39. /// Type of return to use when returning objects from a parcel
  40. /// </summary>
  41. public enum ObjectReturnType : uint
  42. {
  43. /// <summary></summary>
  44. None = 0,
  45. /// <summary>Return objects owned by parcel owner</summary>
  46. Owner = 1 << 1,
  47. /// <summary>Return objects set to group</summary>
  48. Group = 1 << 2,
  49. /// <summary>Return objects not owned by parcel owner or set to group</summary>
  50. Other = 1 << 3,
  51. /// <summary>Return a specific list of objects on parcel</summary>
  52. List = 1 << 4,
  53. /// <summary>Return objects that are marked for-sale</summary>
  54. Sell = 1 << 5
  55. }
  56. /// <summary>
  57. /// Blacklist/Whitelist flags used in parcels Access List
  58. /// </summary>
  59. public enum ParcelAccessFlags : uint
  60. {
  61. /// <summary>Agent is denied access</summary>
  62. NoAccess = 0,
  63. /// <summary>Agent is granted access</summary>
  64. Access = 1
  65. }
  66. /// <summary>
  67. /// The result of a request for parcel properties
  68. /// </summary>
  69. public enum ParcelResult : int
  70. {
  71. /// <summary>No matches were found for the request</summary>
  72. NoData = -1,
  73. /// <summary>Request matched a single parcel</summary>
  74. Single = 0,
  75. /// <summary>Request matched multiple parcels</summary>
  76. Multiple = 1
  77. }
  78. /// <summary>
  79. /// Flags used in the ParcelAccessListRequest packet to specify whether
  80. /// we want the access list (whitelist), ban list (blacklist), or both
  81. /// </summary>
  82. [Flags]
  83. public enum AccessList : uint
  84. {
  85. /// <summary>Request the access list</summary>
  86. Access = 1 << 0,
  87. /// <summary>Request the ban list</summary>
  88. Ban = 1 << 1,
  89. /// <summary>Request both White and Black lists</summary>
  90. Both = Access | Ban
  91. }
  92. /// <summary>
  93. /// Sequence ID in ParcelPropertiesReply packets (sent when avatar
  94. /// tries to cross a parcel border)
  95. /// </summary>
  96. public enum ParcelPropertiesStatus : int
  97. {
  98. /// <summary>Parcel is currently selected</summary>
  99. ParcelSelected = -10000,
  100. /// <summary>Parcel restricted to a group the avatar is not a
  101. /// member of</summary>
  102. CollisionNotInGroup = -20000,
  103. /// <summary>Avatar is banned from the parcel</summary>
  104. CollisionBanned = -30000,
  105. /// <summary>Parcel is restricted to an access list that the
  106. /// avatar is not on</summary>
  107. CollisionNotOnAccessList = -40000,
  108. /// <summary>Response to hovering over a parcel</summary>
  109. HoveredOverParcel = -50000
  110. }
  111. /// <summary>
  112. /// The tool to use when modifying terrain levels
  113. /// </summary>
  114. public enum TerraformAction : byte
  115. {
  116. /// <summary>Level the terrain</summary>
  117. Level = 0,
  118. /// <summary>Raise the terrain</summary>
  119. Raise = 1,
  120. /// <summary>Lower the terrain</summary>
  121. Lower = 2,
  122. /// <summary>Smooth the terrain</summary>
  123. Smooth = 3,
  124. /// <summary>Add random noise to the terrain</summary>
  125. Noise = 4,
  126. /// <summary>Revert terrain to simulator default</summary>
  127. Revert = 5
  128. }
  129. /// <summary>
  130. /// The tool size to use when changing terrain levels
  131. /// </summary>
  132. public enum TerraformBrushSize : byte
  133. {
  134. /// <summary>Small</summary>
  135. Small = 1,
  136. /// <summary>Medium</summary>
  137. Medium = 2,
  138. /// <summary>Large</summary>
  139. Large = 4
  140. }
  141. /// <summary>
  142. /// Reasons agent is denied access to a parcel on the simulator
  143. /// </summary>
  144. public enum AccessDeniedReason : byte
  145. {
  146. /// <summary>Agent is not denied, access is granted</summary>
  147. NotDenied = 0,
  148. /// <summary>Agent is not a member of the group set for the parcel, or which owns the parcel</summary>
  149. NotInGroup = 1,
  150. /// <summary>Agent is not on the parcels specific allow list</summary>
  151. NotOnAllowList = 2,
  152. /// <summary>Agent is on the parcels ban list</summary>
  153. BannedFromParcel = 3,
  154. /// <summary>Unknown</summary>
  155. NoAccess = 4,
  156. /// <summary>Agent is not age verified and parcel settings deny access to non age verified avatars</summary>
  157. NotAgeVerified = 5
  158. }
  159. /// <summary>
  160. /// Parcel overlay type. This is used primarily for highlighting and
  161. /// coloring which is why it is a single integer instead of a set of
  162. /// flags
  163. /// </summary>
  164. /// <remarks>These values seem to be poorly thought out. The first three
  165. /// bits represent a single value, not flags. For example Auction (0x05) is
  166. /// not a combination of OwnedByOther (0x01) and ForSale(0x04). However,
  167. /// the BorderWest and BorderSouth values are bit flags that get attached
  168. /// to the value stored in the first three bits. Bits four, five, and six
  169. /// are unused</remarks>
  170. [Flags]
  171. public enum ParcelOverlayType : byte
  172. {
  173. /// <summary>Public land</summary>
  174. Public = 0,
  175. /// <summary>Land is owned by another avatar</summary>
  176. OwnedByOther = 1,
  177. /// <summary>Land is owned by a group</summary>
  178. OwnedByGroup = 2,
  179. /// <summary>Land is owned by the current avatar</summary>
  180. OwnedBySelf = 3,
  181. /// <summary>Land is for sale</summary>
  182. ForSale = 4,
  183. /// <summary>Land is being auctioned</summary>
  184. Auction = 5,
  185. /// <summary>Land is private</summary>
  186. Private = 32,
  187. /// <summary>To the west of this area is a parcel border</summary>
  188. BorderWest = 64,
  189. /// <summary>To the south of this area is a parcel border</summary>
  190. BorderSouth = 128
  191. }
  192. /// <summary>
  193. /// Various parcel properties
  194. /// </summary>
  195. [Flags]
  196. public enum ParcelFlags : uint
  197. {
  198. /// <summary>No flags set</summary>
  199. None = 0,
  200. /// <summary>Allow avatars to fly (a client-side only restriction)</summary>
  201. AllowFly = 1 << 0,
  202. /// <summary>Allow foreign scripts to run</summary>
  203. AllowOtherScripts = 1 << 1,
  204. /// <summary>This parcel is for sale</summary>
  205. ForSale = 1 << 2,
  206. /// <summary>Allow avatars to create a landmark on this parcel</summary>
  207. AllowLandmark = 1 << 3,
  208. /// <summary>Allows all avatars to edit the terrain on this parcel</summary>
  209. AllowTerraform = 1 << 4,
  210. /// <summary>Avatars have health and can take damage on this parcel.
  211. /// If set, avatars can be killed and sent home here</summary>
  212. AllowDamage = 1 << 5,
  213. /// <summary>Foreign avatars can create objects here</summary>
  214. CreateObjects = 1 << 6,
  215. /// <summary>All objects on this parcel can be purchased</summary>
  216. ForSaleObjects = 1 << 7,
  217. /// <summary>Access is restricted to a group</summary>
  218. UseAccessGroup = 1 << 8,
  219. /// <summary>Access is restricted to a whitelist</summary>
  220. UseAccessList = 1 << 9,
  221. /// <summary>Ban blacklist is enabled</summary>
  222. UseBanList = 1 << 10,
  223. /// <summary>Unknown</summary>
  224. UsePassList = 1 << 11,
  225. /// <summary>List this parcel in the search directory</summary>
  226. ShowDirectory = 1 << 12,
  227. /// <summary>Allow personally owned parcels to be deeded to group</summary>
  228. AllowDeedToGroup = 1 << 13,
  229. /// <summary>If Deeded, owner contributes required tier to group parcel is deeded to</summary>
  230. ContributeWithDeed = 1 << 14,
  231. /// <summary>Restrict sounds originating on this parcel to the
  232. /// parcel boundaries</summary>
  233. SoundLocal = 1 << 15,
  234. /// <summary>Objects on this parcel are sold when the land is
  235. /// purchsaed</summary>
  236. SellParcelObjects = 1 << 16,
  237. /// <summary>Allow this parcel to be published on the web</summary>
  238. AllowPublish = 1 << 17,
  239. /// <summary>The information for this parcel is mature content</summary>
  240. MaturePublish = 1 << 18,
  241. /// <summary>The media URL is an HTML page</summary>
  242. UrlWebPage = 1 << 19,
  243. /// <summary>The media URL is a raw HTML string</summary>
  244. UrlRawHtml = 1 << 20,
  245. /// <summary>Restrict foreign object pushes</summary>
  246. RestrictPushObject = 1 << 21,
  247. /// <summary>Ban all non identified/transacted avatars</summary>
  248. DenyAnonymous = 1 << 22,
  249. // <summary>Ban all identified avatars [OBSOLETE]</summary>
  250. //[Obsolete]
  251. // This was obsoleted in 1.19.0 but appears to be recycled and is used on linden homes parcels
  252. LindenHome = 1 << 23,
  253. // <summary>Ban all transacted avatars [OBSOLETE]</summary>
  254. //[Obsolete]
  255. //DenyTransacted = 1 << 24,
  256. /// <summary>Allow group-owned scripts to run</summary>
  257. AllowGroupScripts = 1 << 25,
  258. /// <summary>Allow object creation by group members or group
  259. /// objects</summary>
  260. CreateGroupObjects = 1 << 26,
  261. /// <summary>Allow all objects to enter this parcel</summary>
  262. AllowAPrimitiveEntry = 1 << 27,
  263. /// <summary>Only allow group and owner objects to enter this parcel</summary>
  264. AllowGroupObjectEntry = 1 << 28,
  265. /// <summary>Voice Enabled on this parcel</summary>
  266. AllowVoiceChat = 1 << 29,
  267. /// <summary>Use Estate Voice channel for Voice on this parcel</summary>
  268. UseEstateVoiceChan = 1 << 30,
  269. /// <summary>Deny Age Unverified Users</summary>
  270. DenyAgeUnverified = 1U << 31
  271. }
  272. /// <summary>
  273. /// Parcel ownership status
  274. /// </summary>
  275. public enum ParcelStatus : sbyte
  276. {
  277. /// <summary>Placeholder</summary>
  278. None = -1,
  279. /// <summary>Parcel is leased (owned) by an avatar or group</summary>
  280. Leased = 0,
  281. /// <summary>Parcel is in process of being leased (purchased) by an avatar or group</summary>
  282. LeasePending = 1,
  283. /// <summary>Parcel has been abandoned back to Governor Linden</summary>
  284. Abandoned = 2
  285. }
  286. /// <summary>
  287. /// Category parcel is listed in under search
  288. /// </summary>
  289. public enum ParcelCategory : sbyte
  290. {
  291. /// <summary>No assigned category</summary>
  292. None = 0,
  293. /// <summary>Linden Infohub or public area</summary>
  294. Linden,
  295. /// <summary>Adult themed area</summary>
  296. Adult,
  297. /// <summary>Arts and Culture</summary>
  298. Arts,
  299. /// <summary>Business</summary>
  300. Business,
  301. /// <summary>Educational</summary>
  302. Educational,
  303. /// <summary>Gaming</summary>
  304. Gaming,
  305. /// <summary>Hangout or Club</summary>
  306. Hangout,
  307. /// <summary>Newcomer friendly</summary>
  308. Newcomer,
  309. /// <summary>Parks and Nature</summary>
  310. Park,
  311. /// <summary>Residential</summary>
  312. Residential,
  313. /// <summary>Shopping</summary>
  314. Shopping,
  315. /// <summary>Not Used?</summary>
  316. Stage,
  317. /// <summary>Other</summary>
  318. Other,
  319. /// <summary>Not an actual category, only used for queries</summary>
  320. Any = -1
  321. }
  322. /// <summary>
  323. /// Type of teleport landing for a parcel
  324. /// </summary>
  325. public enum LandingType : byte
  326. {
  327. /// <summary>Unset, simulator default</summary>
  328. None = 0,
  329. /// <summary>Specific landing point set for this parcel</summary>
  330. LandingPoint = 1,
  331. /// <summary>No landing point set, direct teleports enabled for
  332. /// this parcel</summary>
  333. Direct = 2
  334. }
  335. /// <summary>
  336. /// Parcel Media Command used in ParcelMediaCommandMessage
  337. /// </summary>
  338. public enum ParcelMediaCommand : uint
  339. {
  340. /// <summary>Stop the media stream and go back to the first frame</summary>
  341. Stop = 0,
  342. /// <summary>Pause the media stream (stop playing but stay on current frame)</summary>
  343. Pause,
  344. /// <summary>Start the current media stream playing and stop when the end is reached</summary>
  345. Play,
  346. /// <summary>Start the current media stream playing,
  347. /// loop to the beginning when the end is reached and continue to play</summary>
  348. Loop,
  349. /// <summary>Specifies the texture to replace with video</summary>
  350. /// <remarks>If passing the key of a texture, it must be explicitly typecast as a key,
  351. /// not just passed within double quotes.</remarks>
  352. Texture,
  353. /// <summary>Specifies the movie URL (254 characters max)</summary>
  354. URL,
  355. /// <summary>Specifies the time index at which to begin playing</summary>
  356. Time,
  357. /// <summary>Specifies a single agent to apply the media command to</summary>
  358. Agent,
  359. /// <summary>Unloads the stream. While the stop command sets the texture to the first frame of the movie,
  360. /// unload resets it to the real texture that the movie was replacing.</summary>
  361. Unload,
  362. /// <summary>Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties
  363. /// (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter.</summary>
  364. AutoAlign,
  365. /// <summary>Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only).
  366. /// Use "text/html" for HTML.</summary>
  367. Type,
  368. /// <summary>Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only).</summary>
  369. /// <remarks>This might still not be working</remarks>
  370. Size,
  371. /// <summary>Sets a description for the media being displayed (1.19.1 RC0 and later only).</summary>
  372. Desc
  373. }
  374. #endregion Enums
  375. #region Structs
  376. /// <summary>
  377. /// Some information about a parcel of land returned from a DirectoryManager search
  378. /// </summary>
  379. public struct ParcelInfo
  380. {
  381. /// <summary>Global Key of record</summary>
  382. public UUID ID;
  383. /// <summary>Parcel Owners <seealso cref="UUID"/></summary>
  384. public UUID OwnerID;
  385. /// <summary>Name field of parcel, limited to 128 characters</summary>
  386. public string Name;
  387. /// <summary>Description field of parcel, limited to 256 characters</summary>
  388. public string Description;
  389. /// <summary>Total Square meters of parcel</summary>
  390. public int ActualArea;
  391. /// <summary>Total area billable as Tier, for group owned land this will be 10% less than ActualArea</summary>
  392. public int BillableArea;
  393. /// <summary>True of parcel is in Mature simulator</summary>
  394. public bool Mature;
  395. /// <summary>Grid global X position of parcel</summary>
  396. public float GlobalX;
  397. /// <summary>Grid global Y position of parcel</summary>
  398. public float GlobalY;
  399. /// <summary>Grid global Z position of parcel (not used)</summary>
  400. public float GlobalZ;
  401. /// <summary>Name of simulator parcel is located in</summary>
  402. public string SimName;
  403. /// <summary>Texture <seealso cref="T:OpenMetaverse.UUID"/> of parcels display picture</summary>
  404. public UUID SnapshotID;
  405. /// <summary>Float representing calculated traffic based on time spent on parcel by avatars</summary>
  406. public float Dwell;
  407. /// <summary>Sale price of parcel (not used)</summary>
  408. public int SalePrice;
  409. /// <summary>Auction ID of parcel</summary>
  410. public int AuctionID;
  411. }
  412. /// <summary>
  413. /// Parcel Media Information
  414. /// </summary>
  415. public struct ParcelMedia
  416. {
  417. /// <summary>A byte, if 0x1 viewer should auto scale media to fit object</summary>
  418. public bool MediaAutoScale;
  419. /// <summary>A boolean, if true the viewer should loop the media</summary>
  420. public bool MediaLoop;
  421. /// <summary>The Asset UUID of the Texture which when applied to a
  422. /// primitive will display the media</summary>
  423. public UUID MediaID;
  424. /// <summary>A URL which points to any Quicktime supported media type</summary>
  425. public string MediaURL;
  426. /// <summary>A description of the media</summary>
  427. public string MediaDesc;
  428. /// <summary>An Integer which represents the height of the media</summary>
  429. public int MediaHeight;
  430. /// <summary>An integer which represents the width of the media</summary>
  431. public int MediaWidth;
  432. /// <summary>A string which contains the mime type of the media</summary>
  433. public string MediaType;
  434. }
  435. #endregion Structs
  436. #region Parcel Class
  437. /// <summary>
  438. /// Parcel of land, a portion of virtual real estate in a simulator
  439. /// </summary>
  440. public class Parcel
  441. {
  442. /// <summary>The total number of contiguous 4x4 meter blocks your agent owns within this parcel</summary>
  443. public int SelfCount;
  444. /// <summary>The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own</summary>
  445. public int OtherCount;
  446. /// <summary>Deprecated, Value appears to always be 0</summary>
  447. public int PublicCount;
  448. /// <summary>Simulator-local ID of this parcel</summary>
  449. public int LocalID;
  450. /// <summary>UUID of the owner of this parcel</summary>
  451. public UUID OwnerID;
  452. /// <summary>Whether the land is deeded to a group or not</summary>
  453. public bool IsGroupOwned;
  454. /// <summary></summary>
  455. public uint AuctionID;
  456. /// <summary>Date land was claimed</summary>
  457. public DateTime ClaimDate;
  458. /// <summary>Appears to always be zero</summary>
  459. public int ClaimPrice;
  460. /// <summary>This field is no longer used</summary>
  461. public int RentPrice;
  462. /// <summary>Minimum corner of the axis-aligned bounding box for this
  463. /// parcel</summary>
  464. public Vector3 AABBMin;
  465. /// <summary>Maximum corner of the axis-aligned bounding box for this
  466. /// parcel</summary>
  467. public Vector3 AABBMax;
  468. /// <summary>Bitmap describing land layout in 4x4m squares across the
  469. /// entire region</summary>
  470. public byte[] Bitmap;
  471. /// <summary>Total parcel land area</summary>
  472. public int Area;
  473. /// <summary></summary>
  474. public ParcelStatus Status;
  475. /// <summary>Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used</summary>
  476. public int SimWideMaxPrims;
  477. /// <summary>Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel
  478. /// owned by the agent or group that owns this parcel</summary>
  479. public int SimWideTotalPrims;
  480. /// <summary>Maximum number of primitives this parcel supports</summary>
  481. public int MaxPrims;
  482. /// <summary>Total number of primitives on this parcel</summary>
  483. public int TotalPrims;
  484. /// <summary>For group-owned parcels this indicates the total number of prims deeded to the group,
  485. /// for parcels owned by an individual this inicates the number of prims owned by the individual</summary>
  486. public int OwnerPrims;
  487. /// <summary>Total number of primitives owned by the parcel group on
  488. /// this parcel, or for parcels owned by an individual with a group set the
  489. /// total number of prims set to that group.</summary>
  490. public int GroupPrims;
  491. /// <summary>Total number of prims owned by other avatars that are not set to group, or not the parcel owner</summary>
  492. public int OtherPrims;
  493. /// <summary>A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect
  494. /// the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed</summary>
  495. public float ParcelPrimBonus;
  496. /// <summary>Autoreturn value in minutes for others' objects</summary>
  497. public int OtherCleanTime;
  498. /// <summary></summary>
  499. public ParcelFlags Flags;
  500. /// <summary>Sale price of the parcel, only useful if ForSale is set</summary>
  501. /// <remarks>The SalePrice will remain the same after an ownership
  502. /// transfer (sale), so it can be used to see the purchase price after
  503. /// a sale if the new owner has not changed it</remarks>
  504. public int SalePrice;
  505. /// <summary>Parcel Name</summary>
  506. public string Name;
  507. /// <summary>Parcel Description</summary>
  508. public string Desc;
  509. /// <summary>URL For Music Stream</summary>
  510. public string MusicURL;
  511. /// <summary></summary>
  512. public UUID GroupID;
  513. /// <summary>Price for a temporary pass</summary>
  514. public int PassPrice;
  515. /// <summary>How long is pass valid for</summary>
  516. public float PassHours;
  517. /// <summary></summary>
  518. public ParcelCategory Category;
  519. /// <summary>Key of authorized buyer</summary>
  520. public UUID AuthBuyerID;
  521. /// <summary>Key of parcel snapshot</summary>
  522. public UUID SnapshotID;
  523. /// <summary>The landing point location</summary>
  524. public Vector3 UserLocation;
  525. /// <summary>The landing point LookAt</summary>
  526. public Vector3 UserLookAt;
  527. /// <summary>The type of landing enforced from the <see cref="LandingType"/> enum</summary>
  528. public LandingType Landing;
  529. /// <summary></summary>
  530. public float Dwell;
  531. /// <summary></summary>
  532. public bool RegionDenyAnonymous;
  533. /// <summary></summary>
  534. public bool RegionPushOverride;
  535. /// <summary>Access list of who is whitelisted on this
  536. /// parcel</summary>
  537. public List<ParcelManager.ParcelAccessEntry> AccessWhiteList;
  538. /// <summary>Access list of who is blacklisted on this
  539. /// parcel</summary>
  540. public List<ParcelManager.ParcelAccessEntry> AccessBlackList;
  541. /// <summary>TRUE of region denies access to age unverified users</summary>
  542. public bool RegionDenyAgeUnverified;
  543. /// <summary>true to obscure (hide) media url</summary>
  544. public bool ObscureMedia;
  545. /// <summary>true to obscure (hide) music url</summary>
  546. public bool ObscureMusic;
  547. /// <summary>A struct containing media details</summary>
  548. public ParcelMedia Media;
  549. /// <summary>
  550. /// Displays a parcel object in string format
  551. /// </summary>
  552. /// <returns>string containing key=value pairs of a parcel object</returns>
  553. public override string ToString()
  554. {
  555. string result = "";
  556. Type parcelType = this.GetType();
  557. FieldInfo[] fields = parcelType.GetFields();
  558. foreach (FieldInfo field in fields)
  559. {
  560. result += (field.Name + " = " + field.GetValue(this) + " ");
  561. }
  562. return result;
  563. }
  564. /// <summary>
  565. /// Defalt constructor
  566. /// </summary>
  567. /// <param name="localID">Local ID of this parcel</param>
  568. public Parcel(int localID)
  569. {
  570. LocalID = localID;
  571. ClaimDate = Utils.Epoch;
  572. Bitmap = Utils.EmptyBytes;
  573. Name = String.Empty;
  574. Desc = String.Empty;
  575. MusicURL = String.Empty;
  576. AccessWhiteList = new List<ParcelManager.ParcelAccessEntry>(0);
  577. AccessBlackList = new List<ParcelManager.ParcelAccessEntry>(0);
  578. Media = new ParcelMedia();
  579. }
  580. /// <summary>
  581. /// Update the simulator with any local changes to this Parcel object
  582. /// </summary>
  583. /// <param name="simulator">Simulator to send updates to</param>
  584. /// <param name="wantReply">Whether we want the simulator to confirm
  585. /// the update with a reply packet or not</param>
  586. public void Update(Simulator simulator, bool wantReply)
  587. {
  588. Uri url = simulator.Caps.CapabilityURI("ParcelPropertiesUpdate");
  589. if (url != null)
  590. {
  591. ParcelPropertiesUpdateMessage req = new ParcelPropertiesUpdateMessage();
  592. req.AuthBuyerID = this.AuthBuyerID;
  593. req.Category = this.Category;
  594. req.Desc = this.Desc;
  595. req.GroupID = this.GroupID;
  596. req.Landing = this.Landing;
  597. req.LocalID = this.LocalID;
  598. req.MediaAutoScale = this.Media.MediaAutoScale;
  599. req.MediaDesc = this.Media.MediaDesc;
  600. req.MediaHeight = this.Media.MediaHeight;
  601. req.MediaID = this.Media.MediaID;
  602. req.MediaLoop = this.Media.MediaLoop;
  603. req.MediaType = this.Media.MediaType;
  604. req.MediaURL = this.Media.MediaURL;
  605. req.MediaWidth = this.Media.MediaWidth;
  606. req.MusicURL = this.MusicURL;
  607. req.Name = this.Name;
  608. req.ObscureMedia = this.ObscureMedia;
  609. req.ObscureMusic = this.ObscureMusic;
  610. req.ParcelFlags = this.Flags;
  611. req.PassHours = this.PassHours;
  612. req.PassPrice = (uint)this.PassPrice;
  613. req.SalePrice = (uint)this.SalePrice;
  614. req.SnapshotID = this.SnapshotID;
  615. req.UserLocation = this.UserLocation;
  616. req.UserLookAt = this.UserLookAt;
  617. OSDMap body = req.Serialize();
  618. CapsClient capsPost = new CapsClient(url);
  619. capsPost.BeginGetResponse(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
  620. }
  621. else
  622. {
  623. ParcelPropertiesUpdatePacket request = new ParcelPropertiesUpdatePacket();
  624. request.AgentData.AgentID = simulator.Client.Self.AgentID;
  625. request.AgentData.SessionID = simulator.Client.Self.SessionID;
  626. request.ParcelData.LocalID = this.LocalID;
  627. request.ParcelData.AuthBuyerID = this.AuthBuyerID;
  628. request.ParcelData.Category = (byte)this.Category;
  629. request.ParcelData.Desc = Utils.StringToBytes(this.Desc);
  630. request.ParcelData.GroupID = this.GroupID;
  631. request.ParcelData.LandingType = (byte)this.Landing;
  632. request.ParcelData.MediaAutoScale = (this.Media.MediaAutoScale) ? (byte)0x1 : (byte)0x0;
  633. request.ParcelData.MediaID = this.Media.MediaID;
  634. request.ParcelData.MediaURL = Utils.StringToBytes(this.Media.MediaURL.ToString());
  635. request.ParcelData.MusicURL = Utils.StringToBytes(this.MusicURL.ToString());
  636. request.ParcelData.Name = Utils.StringToBytes(this.Name);
  637. if (wantReply) request.ParcelData.Flags = 1;
  638. request.ParcelData.ParcelFlags = (uint)this.Flags;
  639. request.ParcelData.PassHours = this.PassHours;
  640. request.ParcelData.PassPrice = this.PassPrice;
  641. request.ParcelData.SalePrice = this.SalePrice;
  642. request.ParcelData.SnapshotID = this.SnapshotID;
  643. request.ParcelData.UserLocation = this.UserLocation;
  644. request.ParcelData.UserLookAt = this.UserLookAt;
  645. simulator.SendPacket(request);
  646. }
  647. UpdateOtherCleanTime(simulator);
  648. }
  649. /// <summary>
  650. /// Set Autoreturn time
  651. /// </summary>
  652. /// <param name="simulator">Simulator to send the update to</param>
  653. public void UpdateOtherCleanTime(Simulator simulator)
  654. {
  655. ParcelSetOtherCleanTimePacket request = new ParcelSetOtherCleanTimePacket();
  656. request.AgentData.AgentID = simulator.Client.Self.AgentID;
  657. request.AgentData.SessionID = simulator.Client.Self.SessionID;
  658. request.ParcelData.LocalID = this.LocalID;
  659. request.ParcelData.OtherCleanTime = this.OtherCleanTime;
  660. simulator.SendPacket(request);
  661. }
  662. }
  663. #endregion Parcel Class
  664. /// <summary>
  665. /// Parcel (subdivided simulator lots) subsystem
  666. /// </summary>
  667. public class ParcelManager
  668. {
  669. #region Structs
  670. /// <summary>
  671. /// Parcel Accesslist
  672. /// </summary>
  673. public struct ParcelAccessEntry
  674. {
  675. /// <summary>Agents <seealso cref="T:OpenMetaverse.UUID"/></summary>
  676. public UUID AgentID;
  677. /// <summary></summary>
  678. public DateTime Time;
  679. /// <summary>Flags for specific entry in white/black lists</summary>
  680. public AccessList Flags;
  681. }
  682. /// <summary>
  683. /// Owners of primitives on parcel
  684. /// </summary>
  685. public struct ParcelPrimOwners
  686. {
  687. /// <summary>Prim Owners <seealso cref="T:OpenMetaverse.UUID"/></summary>
  688. public UUID OwnerID;
  689. /// <summary>True of owner is group</summary>
  690. public bool IsGroupOwned;
  691. /// <summary>Total count of prims owned by OwnerID</summary>
  692. public int Count;
  693. /// <summary>true of OwnerID is currently online and is not a group</summary>
  694. public bool OnlineStatus;
  695. /// <summary>The date of the most recent prim left by OwnerID</summary>
  696. public DateTime NewestPrim;
  697. }
  698. #endregion Structs
  699. #region Delegates
  700. /// <summary>
  701. /// Called once parcel resource usage information has been collected
  702. /// </summary>
  703. /// <param name="success">Indicates if operation was successfull</param>
  704. /// <param name="info">Parcel resource usage information</param>
  705. public delegate void LandResourcesCallback(bool success, LandResourcesInfo info);
  706. /// <summary>The event subscribers. null if no subcribers</summary>
  707. private EventHandler<ParcelDwellReplyEventArgs> m_DwellReply;
  708. /// <summary>Raises the ParcelDwellReply event</summary>
  709. /// <param name="e">A ParcelDwellReplyEventArgs object containing the
  710. /// data returned from the simulator</param>
  711. protected virtual void OnParcelDwellReply(ParcelDwellReplyEventArgs e)
  712. {
  713. EventHandler<ParcelDwellReplyEventArgs> handler = m_DwellReply;
  714. if (handler != null)
  715. handler(this, e);
  716. }
  717. /// <summary>Thread sync lock object</summary>
  718. private readonly object m_DwellReplyLock = new object();
  719. /// <summary>Raised when the simulator responds to a <see cref="RequestDwell"/> request</summary>
  720. public event EventHandler<ParcelDwellReplyEventArgs> ParcelDwellReply
  721. {
  722. add { lock (m_DwellReplyLock) { m_DwellReply += value; } }
  723. remove { lock (m_DwellReplyLock) { m_DwellReply -= value; } }
  724. }
  725. /// <summary>The event subscribers. null if no subcribers</summary>
  726. private EventHandler<ParcelInfoReplyEventArgs> m_ParcelInfo;
  727. /// <summary>Raises the ParcelInfoReply event</summary>
  728. /// <param name="e">A ParcelInfoReplyEventArgs object containing the
  729. /// data returned from the simulator</param>
  730. protected virtual void OnParcelInfoReply(ParcelInfoReplyEventArgs e)
  731. {
  732. EventHandler<ParcelInfoReplyEventArgs> handler = m_ParcelInfo;
  733. if (handler != null)
  734. handler(this, e);
  735. }
  736. /// <summary>Thread sync lock object</summary>
  737. private readonly object m_ParcelInfoLock = new object();
  738. /// <summary>Raised when the simulator responds to a <see cref="RequestParcelInfo"/> request</summary>
  739. public event EventHandler<ParcelInfoReplyEventArgs> ParcelInfoReply
  740. {
  741. add { lock (m_ParcelInfoLock) { m_ParcelInfo += value; } }
  742. remove { lock (m_ParcelInfoLock) { m_ParcelInfo -= value; } }
  743. }
  744. /// <summary>The event subscribers. null if no subcribers</summary>
  745. private EventHandler<ParcelPropertiesEventArgs> m_ParcelProperties;
  746. /// <summary>Raises the ParcelProperties event</summary>
  747. /// <param name="e">A ParcelPropertiesEventArgs object containing the
  748. /// data returned from the simulator</param>
  749. protected virtual void OnParcelProperties(ParcelPropertiesEventArgs e)
  750. {
  751. EventHandler<ParcelPropertiesEventArgs> handler = m_ParcelProperties;
  752. if (handler != null)
  753. handler(this, e);
  754. }
  755. /// <summary>Thread sync lock object</summary>
  756. private readonly object m_ParcelPropertiesLock = new object();
  757. /// <summary>Raised when the simulator responds to a <see cref="RequestParcelProperties"/> request</summary>
  758. public event EventHandler<ParcelPropertiesEventArgs> ParcelProperties
  759. {
  760. add { lock (m_ParcelPropertiesLock) { m_ParcelProperties += value; } }
  761. remove { lock (m_ParcelPropertiesLock) { m_ParcelProperties -= value; } }
  762. }
  763. /// <summary>The event subscribers. null if no subcribers</summary>
  764. private EventHandler<ParcelAccessListReplyEventArgs> m_ParcelACL;
  765. /// <summary>Raises the ParcelAccessListReply event</summary>
  766. /// <param name="e">A ParcelAccessListReplyEventArgs object containing the
  767. /// data returned from the simulator</param>
  768. protected virtual void OnParcelAccessListReply(ParcelAccessListReplyEventArgs e)
  769. {
  770. EventHandler<ParcelAccessListReplyEventArgs> handler = m_ParcelACL;
  771. if (handler != null)
  772. handler(this, e);
  773. }
  774. /// <summary>Thread sync lock object</summary>
  775. private readonly object m_ParcelACLLock = new object();
  776. /// <summary>Raised when the simulator responds to a <see cref="RequestParcelAccessList"/> request</summary>
  777. public event EventHandler<ParcelAccessListReplyEventArgs> ParcelAccessListReply
  778. {
  779. add { lock (m_ParcelACLLock) { m_ParcelACL += value; } }
  780. remove { lock (m_ParcelACLLock) { m_ParcelACL -= value; } }
  781. }
  782. /// <summary>The event subscribers. null if no subcribers</summary>
  783. private EventHandler<ParcelObjectOwnersReplyEventArgs> m_ParcelObjectOwnersReply;
  784. /// <summary>Raises the ParcelObjectOwnersReply event</summary>
  785. /// <param name="e">A ParcelObjectOwnersReplyEventArgs object containing the
  786. /// data returned from the simulator</param>
  787. protected virtual void OnParcelObjectOwnersReply(ParcelObjectOwnersReplyEventArgs e)
  788. {
  789. EventHandler<ParcelObjectOwnersReplyEventArgs> handler = m_ParcelObjectOwnersReply;
  790. if (handler != null)
  791. handler(this, e);
  792. }
  793. /// <summary>Thread sync lock object</summary>
  794. private readonly object m_ParcelObjectOwnersLock = new object();
  795. /// <summary>Raised when the simulator responds to a <see cref="RequestObjectOwners"/> request</summary>
  796. public event EventHandler<ParcelObjectOwnersReplyEventArgs> ParcelObjectOwnersReply
  797. {
  798. add { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply += value; } }
  799. remove { lock (m_ParcelObjectOwnersLock) { m_ParcelObjectOwnersReply -= value; } }
  800. }
  801. /// <summary>The event subscribers. null if no subcribers</summary>
  802. private EventHandler<SimParcelsDownloadedEventArgs> m_SimParcelsDownloaded;
  803. /// <summary>Raises the SimParcelsDownloaded event</summary>
  804. /// <param name="e">A SimParcelsDownloadedEventArgs object containing the
  805. /// data returned from the simulator</param>
  806. protected virtual void OnSimParcelsDownloaded(SimParcelsDownloadedEventArgs e)
  807. {
  808. EventHandler<SimParcelsDownloadedEventArgs> handler = m_SimParcelsDownloaded;
  809. if (handler != null)
  810. handler(this, e);
  811. }
  812. /// <summary>Thread sync lock object</summary>
  813. private readonly object m_SimParcelsDownloadedLock = new object();
  814. /// <summary>Raised when the simulator responds to a <see cref="RequestAllSimParcels"/> request</summary>
  815. public event EventHandler<SimParcelsDownloadedEventArgs> SimParcelsDownloaded
  816. {
  817. add { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded += value; } }
  818. remove { lock (m_SimParcelsDownloadedLock) { m_SimParcelsDownloaded -= value; } }
  819. }
  820. /// <summary>The event subscribers. null if no subcribers</summary>
  821. private EventHandler<ForceSelectObjectsReplyEventArgs> m_ForceSelectObjects;
  822. /// <summary>Raises the ForceSelectObjectsReply event</summary>
  823. /// <param name="e">A ForceSelectObjectsReplyEventArgs object containing the
  824. /// data returned from the simulator</param>
  825. protected virtual void OnForceSelectObjectsReply(ForceSelectObjectsReplyEventArgs e)
  826. {
  827. EventHandler<ForceSelectObjectsReplyEventArgs> handler = m_ForceSelectObjects;
  828. if (handler != null)
  829. handler(this, e);
  830. }
  831. /// <summary>Thread sync lock object</summary>
  832. private readonly object m_ForceSelectObjectsLock = new object();
  833. /// <summary>Raised when the simulator responds to a <see cref="RequestForceSelectObjects"/> request</summary>
  834. public event EventHandler<ForceSelectObjectsReplyEventArgs> ForceSelectObjectsReply
  835. {
  836. add { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects += value; } }
  837. remove { lock (m_ForceSelectObjectsLock) { m_ForceSelectObjects -= value; } }
  838. }
  839. /// <summary>The event subscribers. null if no subcribers</summary>
  840. private EventHandler<ParcelMediaUpdateReplyEventArgs> m_ParcelMediaUpdateReply;
  841. /// <summary>Raises the ParcelMediaUpdateReply event</summary>
  842. /// <param name="e">A ParcelMediaUpdateReplyEventArgs object containing the
  843. /// data returned from the simulator</param>
  844. protected virtual void OnParcelMediaUpdateReply(ParcelMediaUpdateReplyEventArgs e)
  845. {
  846. EventHandler<ParcelMediaUpdateReplyEventArgs> handler = m_ParcelMediaUpdateReply;
  847. if (handler != null)
  848. handler(this, e);
  849. }
  850. /// <summary>Thread sync lock object</summary>
  851. private readonly object m_ParcelMediaUpdateReplyLock = new object();
  852. /// <summary>Raised when the simulator responds to a Parcel Update request</summary>
  853. public event EventHandler<ParcelMediaUpdateReplyEventArgs> ParcelMediaUpdateReply
  854. {
  855. add { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply += value; } }
  856. remove { lock (m_ParcelMediaUpdateReplyLock) { m_ParcelMediaUpdateReply -= value; } }
  857. }
  858. /// <summary>The event subscribers. null if no subcribers</summary>
  859. private EventHandler<ParcelMediaCommandEventArgs> m_ParcelMediaCommand;
  860. /// <summary>Raises the ParcelMediaCommand event</summary>
  861. /// <param name="e">A ParcelMediaCommandEventArgs object containing the
  862. /// data returned from the simulator</param>
  863. protected virtual void OnParcelMediaCommand(ParcelMediaCommandEventArgs e)
  864. {
  865. EventHandler<ParcelMediaCommandEventArgs> handler = m_ParcelMediaCommand;
  866. if (handler != null)
  867. handler(this, e);
  868. }
  869. /// <summary>Thread sync lock object</summary>
  870. private readonly object m_ParcelMediaCommandLock = new object();
  871. /// <summary>Raised when the parcel your agent is located sends a ParcelMediaCommand</summary>
  872. public event EventHandler<ParcelMediaCommandEventArgs> ParcelMediaCommand
  873. {
  874. add { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand += value; } }
  875. remove { lock (m_ParcelMediaCommandLock) { m_ParcelMediaCommand -= value; } }
  876. }
  877. #endregion Delegates
  878. private GridClient Client;
  879. private AutoResetEvent WaitForSimParcel;
  880. #region Public Methods
  881. /// <summary>
  882. /// Default constructor
  883. /// </summary>
  884. /// <param name="client">A reference to the GridClient object</param>
  885. public ParcelManager(GridClient client)
  886. {
  887. Client = client;
  888. // Setup the callbacks
  889. Client.Network.RegisterCallback(PacketType.ParcelInfoReply, ParcelInfoReplyHandler);
  890. Client.Network.RegisterEventCallback("ParcelObjectOwnersReply", new Caps.EventQueueCallback(ParcelObjectOwnersReplyHandler));
  891. // CAPS packet handler, to allow for Media Data not contained in the message template
  892. Client.Network.RegisterEventCallback("ParcelProperties", new Caps.EventQueueCallback(ParcelPropertiesReplyHandler));
  893. Client.Network.RegisterCallback(PacketType.ParcelDwellReply, ParcelDwellReplyHandler);
  894. Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, ParcelAccessListReplyHandler);
  895. Client.Network.RegisterCallback(PacketType.ForceObjectSelect, SelectParcelObjectsReplyHandler);
  896. Client.Network.RegisterCallback(PacketType.ParcelMediaUpdate, ParcelMediaUpdateHandler);
  897. Client.Network.RegisterCallback(PacketType.ParcelOverlay, ParcelOverlayHandler);
  898. Client.Network.RegisterCallback(PacketType.ParcelMediaCommandMessage, ParcelMediaCommandMessagePacketHandler);
  899. }
  900. /// <summary>
  901. /// Request basic information for a single parcel
  902. /// </summary>
  903. /// <param name="parcelID">Simulator-local ID of the parcel</param>
  904. public void RequestParcelInfo(UUID parcelID)
  905. {
  906. ParcelInfoRequestPacket request = new ParcelInfoRequestPacket();
  907. request.AgentData.AgentID = Client.Self.AgentID;
  908. request.AgentData.SessionID = Client.Self.SessionID;
  909. request.Data.ParcelID = parcelID;
  910. Client.Network.SendPacket(request);
  911. }
  912. /// <summary>
  913. /// Request properties of a single parcel
  914. /// </summary>
  915. /// <param name="simulator">Simulator containing the parcel</param>
  916. /// <param name="localID">Simulator-local ID of the parcel</param>
  917. /// <param name="sequenceID">An arbitrary integer that will be returned
  918. /// with the ParcelProperties reply, useful for distinguishing between
  919. /// multiple simultaneous requests</param>
  920. public void RequestParcelProperties(Simulator simulator, int localID, int sequenceID)
  921. {
  922. ParcelPropertiesRequestByIDPacket request = new ParcelPropertiesRequestByIDPacket();
  923. request.AgentData.AgentID = Client.Self.AgentID;
  924. request.AgentData.SessionID = Client.Self.SessionID;
  925. request.ParcelData.LocalID = localID;
  926. request.ParcelData.SequenceID = sequenceID;
  927. Client.Network.SendPacket(request, simulator);
  928. }
  929. /// <summary>
  930. /// Request the access list for a single parcel
  931. /// </summary>
  932. /// <param name="simulator">Simulator containing the parcel</param>
  933. /// <param name="localID">Simulator-local ID of the parcel</param>
  934. /// <param name="sequenceID">An arbitrary integer that will be returned
  935. /// with the ParcelAccessList reply, useful for distinguishing between
  936. /// multiple simultaneous requests</param>
  937. /// <param name="flags"></param>
  938. public void RequestParcelAccessList(Simulator simulator, int localID, AccessList flags, int sequenceID)
  939. {
  940. ParcelAccessListRequestPacket request = new ParcelAccessListRequestPacket();
  941. request.AgentData.AgentID = Client.Self.AgentID;
  942. request.AgentData.SessionID = Client.Self.SessionID;
  943. request.Data.LocalID = localID;
  944. request.Data.Flags = (uint)flags;
  945. request.Data.SequenceID = sequenceID;
  946. Client.Network.SendPacket(request, simulator);
  947. }
  948. /// <summary>
  949. /// Request properties of parcels using a bounding box selection
  950. /// </summary>
  951. /// <param name="simulator">Simulator containing the parcel</param>
  952. /// <param name="north">Northern boundary of the parcel selection</param>
  953. /// <param name="east">Eastern boundary of the parcel selection</param>
  954. /// <param name="south">Southern boundary of the parcel selection</param>
  955. /// <param name="west">Western boundary of the parcel selection</param>
  956. /// <param name="sequenceID">An arbitrary integer that will be returned
  957. /// with the ParcelProperties reply, useful for distinguishing between
  958. /// different types of parcel property requests</param>
  959. /// <param name="snapSelection">A boolean that is returned with the
  960. /// ParcelProperties reply, useful for snapping focus to a single
  961. /// parcel</param>
  962. public void RequestParcelProperties(Simulator simulator, float north, float east, float south, float west,
  963. int sequenceID, bool snapSelection)
  964. {
  965. ParcelPropertiesRequestPacket request = new ParcelPropertiesRequestPacket();
  966. request.AgentData.AgentID = Client.Self.AgentID;
  967. request.AgentData.SessionID = Client.Self.SessionID;
  968. request.ParcelData.North = north;
  969. request.ParcelData.East = east;
  970. request.ParcelData.South = south;
  971. request.ParcelData.West = west;
  972. request.ParcelData.SequenceID = sequenceID;
  973. request.ParcelData.SnapSelection = snapSelection;
  974. Client.Network.SendPacket(request, simulator);
  975. }
  976. /// <summary>
  977. /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
  978. /// dictionary)
  979. /// </summary>
  980. /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
  981. public void RequestAllSimParcels(Simulator simulator)
  982. {
  983. RequestAllSimParcels(simulator, false, 750);
  984. }
  985. /// <summary>
  986. /// Request all simulator parcel properties (used for populating the <code>Simulator.Parcels</code>
  987. /// dictionary)
  988. /// </summary>
  989. /// <param name="simulator">Simulator to request parcels from (must be connected)</param>
  990. /// <param name="refresh">If TRUE, will force a full refresh</param>
  991. /// <param name="msDelay">Number of milliseconds to pause in between each request</param>
  992. public void RequestAllSimParcels(Simulator simulator, bool refresh, int msDelay)
  993. {
  994. if (simulator.DownloadingParcelMap)
  995. {
  996. Logger.Log("Already downloading parcels in " + simulator.Name, Helpers.LogLevel.Info, Client);
  997. return;
  998. }
  999. else
  1000. {
  1001. simulator.DownloadingParcelMap = true;
  1002. WaitForSimParcel = new AutoResetEvent(false);
  1003. }
  1004. if (refresh)
  1005. {
  1006. for (int y = 0; y < 64; y++)
  1007. for (int x = 0; x < 64; x++)
  1008. simulator.ParcelMap[y, x] = 0;
  1009. }
  1010. Thread th = new Thread(delegate()
  1011. {
  1012. int count = 0, timeouts = 0, y, x;
  1013. for (y = 0; y < 64; y++)
  1014. {
  1015. for (x = 0; x < 64; x++)
  1016. {
  1017. if (!Client.Network.Connected)
  1018. return;
  1019. if (simulator.ParcelMap[y, x] == 0)
  1020. {
  1021. Client.Parcels.RequestParcelProperties(simulator,
  1022. (y + 1) * 4.0f, (x + 1) * 4.0f,
  1023. y * 4.0f, x * 4.0f, int.MaxValue, false);
  1024. // Wait the given amount of time for a reply beforeā€¦

Large files files are truncated, but you can click here to view the full file