PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenMetaverse/Modules/DirectoryManager.cs

https://bitbucket.org/VirtualReality/3rdparty-addon-modules
C# | 1610 lines | 833 code | 180 blank | 597 comment | 41 complexity | dd6272d63a31434713e3d5e3a5b0dafb MD5 | raw file

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

  1. /*
  2. * Copyright (c) 2006-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.Collections.Generic;
  29. using OpenMetaverse.Packets;
  30. using OpenMetaverse.Interfaces;
  31. using OpenMetaverse.Messages.Linden;
  32. namespace OpenMetaverse
  33. {
  34. /// <summary>
  35. /// Access to the data server which allows searching for land, events, people, etc
  36. /// </summary>
  37. public class DirectoryManager
  38. {
  39. #region Enums
  40. /// <summary>Classified Ad categories</summary>
  41. public enum ClassifiedCategories
  42. {
  43. /// <summary>Classified is listed in the Any category</summary>
  44. Any = 0,
  45. /// <summary>Classified is shopping related</summary>
  46. Shopping,
  47. /// <summary>Classified is </summary>
  48. LandRental,
  49. /// <summary></summary>
  50. PropertyRental,
  51. /// <summary></summary>
  52. SpecialAttraction,
  53. /// <summary></summary>
  54. NewProducts,
  55. /// <summary></summary>
  56. Employment,
  57. /// <summary></summary>
  58. Wanted,
  59. /// <summary></summary>
  60. Service,
  61. /// <summary></summary>
  62. Personal
  63. }
  64. /// <summary>Event Categories</summary>
  65. public enum EventCategories
  66. {
  67. /// <summary></summary>
  68. All = 0,
  69. /// <summary></summary>
  70. Discussion = 18,
  71. /// <summary></summary>
  72. Sports = 19,
  73. /// <summary></summary>
  74. LiveMusic = 20,
  75. /// <summary></summary>
  76. Commercial = 22,
  77. /// <summary></summary>
  78. Nightlife = 23,
  79. /// <summary></summary>
  80. Games = 24,
  81. /// <summary></summary>
  82. Pageants = 25,
  83. /// <summary></summary>
  84. Education = 26,
  85. /// <summary></summary>
  86. Arts = 27,
  87. /// <summary></summary>
  88. Charity = 28,
  89. /// <summary></summary>
  90. Miscellaneous = 29
  91. }
  92. /// <summary>
  93. /// Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results.
  94. ///
  95. /// Flags can be combined using the | (pipe) character, not all flags are available in all queries
  96. /// </summary>
  97. [Flags]
  98. public enum DirFindFlags
  99. {
  100. /// <summary>Query the People database</summary>
  101. People = 1 << 0,
  102. /// <summary></summary>
  103. Online = 1 << 1,
  104. // <summary></summary>
  105. //[Obsolete]
  106. //Places = 1 << 2,
  107. /// <summary></summary>
  108. Events = 1 << 3,
  109. /// <summary>Query the Groups database</summary>
  110. Groups = 1 << 4,
  111. /// <summary>Query the Events database</summary>
  112. DateEvents = 1 << 5,
  113. /// <summary>Query the land holdings database for land owned by the currently connected agent</summary>
  114. AgentOwned = 1 << 6,
  115. /// <summary></summary>
  116. ForSale = 1 << 7,
  117. /// <summary>Query the land holdings database for land which is owned by a Group</summary>
  118. GroupOwned = 1 << 8,
  119. // <summary></summary>
  120. //[Obsolete]
  121. //Auction = 1 << 9,
  122. /// <summary>Specifies the query should pre sort the results based upon traffic
  123. /// when searching the Places database</summary>
  124. DwellSort = 1 << 10,
  125. /// <summary></summary>
  126. PgSimsOnly = 1 << 11,
  127. /// <summary></summary>
  128. PicturesOnly = 1 << 12,
  129. /// <summary></summary>
  130. PgEventsOnly = 1 << 13,
  131. /// <summary></summary>
  132. MatureSimsOnly = 1 << 14,
  133. /// <summary>Specifies the query should pre sort the results in an ascending order when searching the land sales database.
  134. /// This flag is only used when searching the land sales database</summary>
  135. SortAsc = 1 << 15,
  136. /// <summary>Specifies the query should pre sort the results using the SalePrice field when searching the land sales database.
  137. /// This flag is only used when searching the land sales database</summary>
  138. PricesSort = 1 << 16,
  139. /// <summary>Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database.
  140. /// This flag is only used when searching the land sales database</summary>
  141. PerMeterSort = 1 << 17,
  142. /// <summary>Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database.
  143. /// This flag is only used when searching the land sales database</summary>
  144. AreaSort = 1 << 18,
  145. /// <summary>Specifies the query should pre sort the results using the Name field when searching the land sales database.
  146. /// This flag is only used when searching the land sales database</summary>
  147. NameSort = 1 << 19,
  148. /// <summary>When set, only parcels less than the specified Price will be included when searching the land sales database.
  149. /// This flag is only used when searching the land sales database</summary>
  150. LimitByPrice = 1 << 20,
  151. /// <summary>When set, only parcels greater than the specified Size will be included when searching the land sales database.
  152. /// This flag is only used when searching the land sales database</summary>
  153. LimitByArea = 1 << 21,
  154. /// <summary></summary>
  155. FilterMature = 1 << 22,
  156. /// <summary></summary>
  157. PGOnly = 1 << 23,
  158. /// <summary>Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases</summary>
  159. IncludePG = 1 << 24,
  160. /// <summary>Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases</summary>
  161. IncludeMature = 1 << 25,
  162. /// <summary>Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases</summary>
  163. IncludeAdult = 1 << 26,
  164. /// <summary></summary>
  165. AdultOnly = 1 << 27
  166. }
  167. /// <summary>
  168. /// Land types to search dataserver for
  169. /// </summary>
  170. [Flags]
  171. public enum SearchTypeFlags
  172. {
  173. /// <summary>Search Auction, Mainland and Estate</summary>
  174. Any = -1,
  175. /// <summary>Land which is currently up for auction</summary>
  176. Auction = 1 << 1,
  177. // <summary>Land available to new landowners (formerly the FirstLand program)</summary>
  178. //[Obsolete]
  179. //Newbie = 1 << 2,
  180. /// <summary>Parcels which are on the mainland (Linden owned) continents</summary>
  181. Mainland = 1 << 3,
  182. /// <summary>Parcels which are on privately owned simulators</summary>
  183. Estate = 1 << 4
  184. }
  185. /// <summary>
  186. /// The content rating of the event
  187. /// </summary>
  188. public enum EventFlags
  189. {
  190. /// <summary>Event is PG</summary>
  191. PG = 0,
  192. /// <summary>Event is Mature</summary>
  193. Mature = 1,
  194. /// <summary>Event is Adult</summary>
  195. Adult = 2
  196. }
  197. /// <summary>
  198. /// Classified Ad Options
  199. /// </summary>
  200. /// <remarks>There appear to be two formats the flags are packed in.
  201. /// This set of flags is for the newer style</remarks>
  202. [Flags]
  203. public enum ClassifiedFlags : byte
  204. {
  205. /// <summary></summary>
  206. None = 1 << 0,
  207. /// <summary></summary>
  208. Mature = 1 << 1,
  209. /// <summary></summary>
  210. Enabled = 1 << 2,
  211. // HasPrice = 1 << 3, // Deprecated
  212. /// <summary></summary>
  213. UpdateTime = 1 << 4,
  214. /// <summary></summary>
  215. AutoRenew = 1 << 5
  216. }
  217. /// <summary>
  218. /// Classified ad query options
  219. /// </summary>
  220. [Flags]
  221. public enum ClassifiedQueryFlags
  222. {
  223. /// <summary>Include all ads in results</summary>
  224. All = PG | Mature | Adult,
  225. /// <summary>Include PG ads in results</summary>
  226. PG = 1 << 2,
  227. /// <summary>Include Mature ads in results</summary>
  228. Mature = 1 << 3,
  229. /// <summary>Include Adult ads in results</summary>
  230. Adult = 1 << 6,
  231. }
  232. /// <summary>
  233. /// The For Sale flag in PlacesReplyData
  234. /// </summary>
  235. public enum PlacesFlags : byte
  236. {
  237. /// <summary>Parcel is not listed for sale</summary>
  238. NotForSale = 0,
  239. /// <summary>Parcel is For Sale</summary>
  240. ForSale = 128
  241. }
  242. #endregion
  243. #region Structs
  244. /// <summary>
  245. /// A classified ad on the grid
  246. /// </summary>
  247. public struct Classified
  248. {
  249. /// <summary>UUID for this ad, useful for looking up detailed
  250. /// information about it</summary>
  251. public UUID ID;
  252. /// <summary>The title of this classified ad</summary>
  253. public string Name;
  254. /// <summary>Flags that show certain options applied to the classified</summary>
  255. public ClassifiedFlags Flags;
  256. /// <summary>Creation date of the ad</summary>
  257. public DateTime CreationDate;
  258. /// <summary>Expiration date of the ad</summary>
  259. public DateTime ExpirationDate;
  260. /// <summary>Price that was paid for this ad</summary>
  261. public int Price;
  262. /// <summary>Print the struct data as a string</summary>
  263. /// <returns>A string containing the field name, and field value</returns>
  264. public override string ToString()
  265. {
  266. return Helpers.StructToString(this);
  267. }
  268. }
  269. /// <summary>
  270. /// A parcel retrieved from the dataserver such as results from the
  271. /// "For-Sale" listings or "Places" Search
  272. /// </summary>
  273. public struct DirectoryParcel
  274. {
  275. /// <summary>The unique dataserver parcel ID</summary>
  276. /// <remarks>This id is used to obtain additional information from the entry
  277. /// by using the <see cref="ParcelManager.InfoRequest"/> method</remarks>
  278. public UUID ID;
  279. /// <summary>A string containing the name of the parcel</summary>
  280. public string Name;
  281. /// <summary>The size of the parcel</summary>
  282. /// <remarks>This field is not returned for Places searches</remarks>
  283. public int ActualArea;
  284. /// <summary>The price of the parcel</summary>
  285. /// <remarks>This field is not returned for Places searches</remarks>
  286. public int SalePrice;
  287. /// <summary>If True, this parcel is flagged to be auctioned</summary>
  288. public bool Auction;
  289. /// <summary>If true, this parcel is currently set for sale</summary>
  290. public bool ForSale;
  291. /// <summary>Parcel traffic</summary>
  292. public float Dwell;
  293. /// <summary>Print the struct data as a string</summary>
  294. /// <returns>A string containing the field name, and field value</returns>
  295. public override string ToString()
  296. {
  297. return Helpers.StructToString(this);
  298. }
  299. }
  300. /// <summary>
  301. /// An Avatar returned from the dataserver
  302. /// </summary>
  303. public struct AgentSearchData
  304. {
  305. /// <summary>Online status of agent</summary>
  306. /// <remarks>This field appears to be obsolete and always returns false</remarks>
  307. public bool Online;
  308. /// <summary>The agents first name</summary>
  309. public string FirstName;
  310. /// <summary>The agents last name</summary>
  311. public string LastName;
  312. /// <summary>The agents <see cref="UUID"/></summary>
  313. public UUID AgentID;
  314. /// <summary>Print the struct data as a string</summary>
  315. /// <returns>A string containing the field name, and field value</returns>
  316. public override string ToString()
  317. {
  318. return Helpers.StructToString(this);
  319. }
  320. }
  321. /// <summary>
  322. /// Response to a "Groups" Search
  323. /// </summary>
  324. public struct GroupSearchData
  325. {
  326. /// <summary>The Group ID</summary>
  327. public UUID GroupID;
  328. /// <summary>The name of the group</summary>
  329. public string GroupName;
  330. /// <summary>The current number of members</summary>
  331. public int Members;
  332. /// <summary>Print the struct data as a string</summary>
  333. /// <returns>A string containing the field name, and field value</returns>
  334. public override string ToString()
  335. {
  336. return Helpers.StructToString(this);
  337. }
  338. }
  339. /// <summary>
  340. /// Parcel information returned from a <see cref="StartPlacesSearch"/> request
  341. /// <para>
  342. /// Represents one of the following:
  343. /// A parcel of land on the grid that has its Show In Search flag set
  344. /// A parcel of land owned by the agent making the request
  345. /// A parcel of land owned by a group the agent making the request is a member of
  346. /// </para>
  347. /// <para>
  348. /// In a request for Group Land, the First record will contain an empty record
  349. /// </para>
  350. /// Note: This is not the same as searching the land for sale data source
  351. /// </summary>
  352. public struct PlacesSearchData
  353. {
  354. /// <summary>The ID of the Agent of Group that owns the parcel</summary>
  355. public UUID OwnerID;
  356. /// <summary>The name</summary>
  357. public string Name;
  358. /// <summary>The description</summary>
  359. public string Desc;
  360. /// <summary>The Size of the parcel</summary>
  361. public int ActualArea;
  362. /// <summary>The billable Size of the parcel, for mainland
  363. /// parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller
  364. /// than the ActualArea. For Estate land this will always be 0</summary>
  365. public int BillableArea;
  366. /// <summary>Indicates the ForSale status of the parcel</summary>
  367. public PlacesFlags Flags;
  368. /// <summary>The Gridwide X position</summary>
  369. public float GlobalX;
  370. /// <summary>The Gridwide Y position</summary>
  371. public float GlobalY;
  372. /// <summary>The Z position of the parcel, or 0 if no landing point set</summary>
  373. public float GlobalZ;
  374. /// <summary>The name of the Region the parcel is located in</summary>
  375. public string SimName;
  376. /// <summary>The Asset ID of the parcels Snapshot texture</summary>
  377. public UUID SnapshotID;
  378. /// <summary>The calculated visitor traffic</summary>
  379. public float Dwell;
  380. /// <summary>The billing product SKU</summary>
  381. /// <remarks>Known values are:
  382. /// <list type="table">
  383. /// <item><term>023</term><description>Mainland / Full Region</description></item>
  384. /// <item><term>024</term><description>Estate / Full Region</description></item>
  385. /// <item><term>027</term><description>Estate / Openspace</description></item>
  386. /// <item><term>029</term><description>Estate / Homestead</description></item>
  387. /// <item><term>129</term><description>Mainland / Homestead (Linden Owned)</description></item>
  388. /// </list>
  389. /// </remarks>
  390. public string SKU;
  391. /// <summary>No longer used, will always be 0</summary>
  392. public int Price;
  393. /// <summary>Get a SL URL for the parcel</summary>
  394. /// <returns>A string, containing a standard SLURL</returns>
  395. public string ToSLurl()
  396. {
  397. float x, y;
  398. Helpers.GlobalPosToRegionHandle(this.GlobalX, this.GlobalY, out x, out y);
  399. return "secondlife://" + this.SimName + "/" + x + "/" + y + "/" + this.GlobalZ;
  400. }
  401. /// <summary>Print the struct data as a string</summary>
  402. /// <returns>A string containing the field name, and field value</returns>
  403. public override string ToString()
  404. {
  405. return Helpers.StructToString(this);
  406. }
  407. }
  408. /// <summary>
  409. /// An "Event" Listing summary
  410. /// </summary>
  411. public struct EventsSearchData
  412. {
  413. /// <summary>The ID of the event creator</summary>
  414. public UUID Owner;
  415. /// <summary>The name of the event</summary>
  416. public string Name;
  417. /// <summary>The events ID</summary>
  418. public uint ID;
  419. /// <summary>A string containing the short date/time the event will begin</summary>
  420. public string Date;
  421. /// <summary>The event start time in Unixtime (seconds since epoch)</summary>
  422. public uint Time;
  423. /// <summary>The events maturity rating</summary>
  424. public EventFlags Flags;
  425. /// <summary>Print the struct data as a string</summary>
  426. /// <returns>A string containing the field name, and field value</returns>
  427. public override string ToString()
  428. {
  429. return Helpers.StructToString(this);
  430. }
  431. }
  432. /// <summary>
  433. /// The details of an "Event"
  434. /// </summary>
  435. public struct EventInfo
  436. {
  437. /// <summary>The events ID</summary>
  438. public uint ID;
  439. /// <summary>The ID of the event creator</summary>
  440. public UUID Creator;
  441. /// <summary>The name of the event</summary>
  442. public string Name;
  443. /// <summary>The category</summary>
  444. public EventCategories Category;
  445. /// <summary>The events description</summary>
  446. public string Desc;
  447. /// <summary>The short date/time the event will begin</summary>
  448. public string Date;
  449. /// <summary>The event start time in Unixtime (seconds since epoch) UTC adjusted</summary>
  450. public uint DateUTC;
  451. /// <summary>The length of the event in minutes</summary>
  452. public uint Duration;
  453. /// <summary>0 if no cover charge applies</summary>
  454. public uint Cover;
  455. /// <summary>The cover charge amount in L$ if applicable</summary>
  456. public uint Amount;
  457. /// <summary>The name of the region where the event is being held</summary>
  458. public string SimName;
  459. /// <summary>The gridwide location of the event</summary>
  460. public Vector3d GlobalPos;
  461. /// <summary>The maturity rating</summary>
  462. public EventFlags Flags;
  463. /// <summary>Get a SL URL for the parcel where the event is hosted</summary>
  464. /// <returns>A string, containing a standard SLURL</returns>
  465. public string ToSLurl()
  466. {
  467. float x, y;
  468. Helpers.GlobalPosToRegionHandle((float)this.GlobalPos.X, (float)this.GlobalPos.Y, out x, out y);
  469. return "secondlife://" + this.SimName + "/" + x + "/" + y + "/" + this.GlobalPos.Z;
  470. }
  471. /// <summary>Print the struct data as a string</summary>
  472. /// <returns>A string containing the field name, and field value</returns>
  473. public override string ToString()
  474. {
  475. return Helpers.StructToString(this);
  476. }
  477. }
  478. #endregion Structs
  479. #region Event delegates, Raise Events
  480. /// <summary>The event subscribers. null if no subcribers</summary>
  481. private EventHandler<EventInfoReplyEventArgs> m_EventInfoReply;
  482. /// <summary>Raises the EventInfoReply event</summary>
  483. /// <param name="e">An EventInfoReplyEventArgs object containing the
  484. /// data returned from the data server</param>
  485. protected virtual void OnEventInfo(EventInfoReplyEventArgs e)
  486. {
  487. EventHandler<EventInfoReplyEventArgs> handler = m_EventInfoReply;
  488. if (handler != null)
  489. handler(this, e);
  490. }
  491. /// <summary>Thread sync lock object</summary>
  492. private readonly object m_EventDetailLock = new object();
  493. /// <summary>Raised when the data server responds to a <see cref="EventInfoRequest"/> request.</summary>
  494. public event EventHandler<EventInfoReplyEventArgs> EventInfoReply
  495. {
  496. add { lock (m_EventDetailLock) { m_EventInfoReply += value; } }
  497. remove { lock (m_EventDetailLock) { m_EventInfoReply -= value; } }
  498. }
  499. /// <summary>The event subscribers. null if no subcribers</summary>
  500. private EventHandler<DirEventsReplyEventArgs> m_DirEvents;
  501. /// <summary>Raises the DirEventsReply event</summary>
  502. /// <param name="e">An DirEventsReplyEventArgs object containing the
  503. /// data returned from the data server</param>
  504. protected virtual void OnDirEvents(DirEventsReplyEventArgs e)
  505. {
  506. EventHandler<DirEventsReplyEventArgs> handler = m_DirEvents;
  507. if (handler != null)
  508. handler(this, e);
  509. }
  510. /// <summary>Thread sync lock object</summary>
  511. private readonly object m_DirEventsLock = new object();
  512. /// <summary>Raised when the data server responds to a <see cref="StartEventsSearch"/> request.</summary>
  513. public event EventHandler<DirEventsReplyEventArgs> DirEventsReply
  514. {
  515. add { lock (m_DirEventsLock) { m_DirEvents += value; } }
  516. remove { lock (m_DirEventsLock) { m_DirEvents -= value; } }
  517. }
  518. /// <summary>The event subscribers. null if no subcribers</summary>
  519. private EventHandler<PlacesReplyEventArgs> m_Places;
  520. /// <summary>Raises the PlacesReply event</summary>
  521. /// <param name="e">A PlacesReplyEventArgs object containing the
  522. /// data returned from the data server</param>
  523. protected virtual void OnPlaces(PlacesReplyEventArgs e)
  524. {
  525. EventHandler<PlacesReplyEventArgs> handler = m_Places;
  526. if (handler != null)
  527. handler(this, e);
  528. }
  529. /// <summary>Thread sync lock object</summary>
  530. private readonly object m_PlacesLock = new object();
  531. /// <summary>Raised when the data server responds to a <see cref="StartPlacesSearch"/> request.</summary>
  532. public event EventHandler<PlacesReplyEventArgs> PlacesReply
  533. {
  534. add { lock (m_PlacesLock) { m_Places += value; } }
  535. remove { lock (m_PlacesLock) { m_Places -= value; } }
  536. }
  537. /// <summary>The event subscribers. null if no subcribers</summary>
  538. private EventHandler<DirPlacesReplyEventArgs> m_DirPlaces;
  539. /// <summary>Raises the DirPlacesReply event</summary>
  540. /// <param name="e">A DirPlacesReplyEventArgs object containing the
  541. /// data returned from the data server</param>
  542. protected virtual void OnDirPlaces(DirPlacesReplyEventArgs e)
  543. {
  544. EventHandler<DirPlacesReplyEventArgs> handler = m_DirPlaces;
  545. if (handler != null)
  546. handler(this, e);
  547. }
  548. /// <summary>Thread sync lock object</summary>
  549. private readonly object m_DirPlacesLock = new object();
  550. /// <summary>Raised when the data server responds to a <see cref="StartDirPlacesSearch"/> request.</summary>
  551. public event EventHandler<DirPlacesReplyEventArgs> DirPlacesReply
  552. {
  553. add { lock (m_DirPlacesLock) { m_DirPlaces += value; } }
  554. remove { lock (m_DirPlacesLock) { m_DirPlaces -= value; } }
  555. }
  556. /// <summary>The event subscribers. null if no subcribers</summary>
  557. private EventHandler<DirClassifiedsReplyEventArgs> m_DirClassifieds;
  558. /// <summary>Raises the DirClassifiedsReply event</summary>
  559. /// <param name="e">A DirClassifiedsReplyEventArgs object containing the
  560. /// data returned from the data server</param>
  561. protected virtual void OnDirClassifieds(DirClassifiedsReplyEventArgs e)
  562. {
  563. EventHandler<DirClassifiedsReplyEventArgs> handler = m_DirClassifieds;
  564. if (handler != null)
  565. handler(this, e);
  566. }
  567. /// <summary>Thread sync lock object</summary>
  568. private readonly object m_DirClassifiedsLock = new object();
  569. /// <summary>Raised when the data server responds to a <see cref="StartClassifiedSearch"/> request.</summary>
  570. public event EventHandler<DirClassifiedsReplyEventArgs> DirClassifiedsReply
  571. {
  572. add { lock (m_DirClassifiedsLock) { m_DirClassifieds += value; } }
  573. remove { lock (m_DirClassifiedsLock) { m_DirClassifieds -= value; } }
  574. }
  575. /// <summary>The event subscribers. null if no subcribers</summary>
  576. private EventHandler<DirGroupsReplyEventArgs> m_DirGroups;
  577. /// <summary>Raises the DirGroupsReply event</summary>
  578. /// <param name="e">A DirGroupsReplyEventArgs object containing the
  579. /// data returned from the data server</param>
  580. protected virtual void OnDirGroups(DirGroupsReplyEventArgs e)
  581. {
  582. EventHandler<DirGroupsReplyEventArgs> handler = m_DirGroups;
  583. if (handler != null)
  584. handler(this, e);
  585. }
  586. /// <summary>Thread sync lock object</summary>
  587. private readonly object m_DirGroupsLock = new object();
  588. /// <summary>Raised when the data server responds to a <see cref="StartGroupSearch"/> request.</summary>
  589. public event EventHandler<DirGroupsReplyEventArgs> DirGroupsReply
  590. {
  591. add { lock (m_DirGroupsLock) { m_DirGroups += value; } }
  592. remove { lock (m_DirGroupsLock) { m_DirGroups -= value; } }
  593. }
  594. /// <summary>The event subscribers. null if no subcribers</summary>
  595. private EventHandler<DirPeopleReplyEventArgs> m_DirPeople;
  596. /// <summary>Raises the DirPeopleReply event</summary>
  597. /// <param name="e">A DirPeopleReplyEventArgs object containing the
  598. /// data returned from the data server</param>
  599. protected virtual void OnDirPeople(DirPeopleReplyEventArgs e)
  600. {
  601. EventHandler<DirPeopleReplyEventArgs> handler = m_DirPeople;
  602. if (handler != null)
  603. handler(this, e);
  604. }
  605. /// <summary>Thread sync lock object</summary>
  606. private readonly object m_DirPeopleLock = new object();
  607. /// <summary>Raised when the data server responds to a <see cref="StartPeopleSearch"/> request.</summary>
  608. public event EventHandler<DirPeopleReplyEventArgs> DirPeopleReply
  609. {
  610. add { lock (m_DirPeopleLock) { m_DirPeople += value; } }
  611. remove { lock (m_DirPeopleLock) { m_DirPeople -= value; } }
  612. }
  613. /// <summary>The event subscribers. null if no subcribers</summary>
  614. private EventHandler<DirLandReplyEventArgs> m_DirLandReply;
  615. /// <summary>Raises the DirLandReply event</summary>
  616. /// <param name="e">A DirLandReplyEventArgs object containing the
  617. /// data returned from the data server</param>
  618. protected virtual void OnDirLand(DirLandReplyEventArgs e)
  619. {
  620. EventHandler<DirLandReplyEventArgs> handler = m_DirLandReply;
  621. if (handler != null)
  622. handler(this, e);
  623. }
  624. /// <summary>Thread sync lock object</summary>
  625. private readonly object m_DirLandLock = new object();
  626. /// <summary>Raised when the data server responds to a <see cref="StartLandSearch"/> request.</summary>
  627. public event EventHandler<DirLandReplyEventArgs> DirLandReply
  628. {
  629. add { lock (m_DirLandLock) { m_DirLandReply += value; } }
  630. remove { lock (m_DirLandLock) { m_DirLandReply -= value; } }
  631. }
  632. #endregion
  633. #region Private Members
  634. private GridClient Client;
  635. #endregion
  636. #region Constructors
  637. /// <summary>
  638. /// Constructs a new instance of the DirectoryManager class
  639. /// </summary>
  640. /// <param name="client">An instance of GridClient</param>
  641. public DirectoryManager(GridClient client)
  642. {
  643. Client = client;
  644. Client.Network.RegisterCallback(PacketType.DirClassifiedReply, DirClassifiedReplyHandler);
  645. // Deprecated, replies come in over capabilities
  646. Client.Network.RegisterCallback(PacketType.DirLandReply, DirLandReplyHandler);
  647. Client.Network.RegisterEventCallback("DirLandReply", DirLandReplyEventHandler);
  648. Client.Network.RegisterCallback(PacketType.DirPeopleReply, DirPeopleReplyHandler);
  649. Client.Network.RegisterCallback(PacketType.DirGroupsReply, DirGroupsReplyHandler);
  650. // Deprecated as of viewer 1.2.3
  651. Client.Network.RegisterCallback(PacketType.PlacesReply, PlacesReplyHandler);
  652. Client.Network.RegisterEventCallback("PlacesReply", PlacesReplyEventHandler);
  653. Client.Network.RegisterCallback(PacketType.DirEventsReply, EventsReplyHandler);
  654. Client.Network.RegisterCallback(PacketType.EventInfoReply, EventInfoReplyHandler);
  655. Client.Network.RegisterCallback(PacketType.DirPlacesReply, DirPlacesReplyHandler);
  656. }
  657. #endregion
  658. #region Public Methods
  659. // Obsoleted due to new Adult search option
  660. [Obsolete("Use Overload with ClassifiedQueryFlags option instead")]
  661. public UUID StartClassifiedSearch(string searchText, ClassifiedCategories category, bool mature)
  662. {
  663. return UUID.Zero;
  664. }
  665. /// <summary>
  666. /// Query the data server for a list of classified ads containing the specified string.
  667. /// Defaults to searching for classified placed in any category, and includes PG, Adult and Mature
  668. /// results.
  669. ///
  670. /// Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming
  671. /// the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received
  672. ///
  673. /// The <see cref="OnClassifiedReply"/> event is raised when a response is received from the simulator
  674. /// </summary>
  675. /// <param name="searchText">A string containing a list of keywords to search for</param>
  676. /// <returns>A UUID to correlate the results when the <see cref="OnClassifiedReply"/> event is raised</returns>
  677. public UUID StartClassifiedSearch(string searchText)
  678. {
  679. return StartClassifiedSearch(searchText, ClassifiedCategories.Any, ClassifiedQueryFlags.All);
  680. }
  681. /// <summary>
  682. /// Query the data server for a list of classified ads which contain specified keywords (Overload)
  683. ///
  684. /// The <see cref="OnClassifiedReply"/> event is raised when a response is received from the simulator
  685. /// </summary>
  686. /// <param name="searchText">A string containing a list of keywords to search for</param>
  687. /// <param name="category">The category to search</param>
  688. /// <param name="queryFlags">A set of flags which can be ORed to modify query options
  689. /// such as classified maturity rating.</param>
  690. /// <returns>A UUID to correlate the results when the <see cref="OnClassifiedReply"/> event is raised</returns>
  691. /// <example>
  692. /// Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature
  693. /// <code>
  694. /// UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature);
  695. /// </code>
  696. /// </example>
  697. /// <remarks>
  698. /// Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming
  699. /// the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received
  700. /// </remarks>
  701. public UUID StartClassifiedSearch(string searchText, ClassifiedCategories category, ClassifiedQueryFlags queryFlags)
  702. {
  703. DirClassifiedQueryPacket query = new DirClassifiedQueryPacket();
  704. UUID queryID = UUID.Random();
  705. query.AgentData.AgentID = Client.Self.AgentID;
  706. query.AgentData.SessionID = Client.Self.SessionID;
  707. query.QueryData.Category = (uint)category;
  708. query.QueryData.QueryFlags = (uint)queryFlags;
  709. query.QueryData.QueryID = queryID;
  710. query.QueryData.QueryText = Utils.StringToBytes(searchText);
  711. Client.Network.SendPacket(query);
  712. return queryID;
  713. }
  714. /// <summary>
  715. /// Starts search for places (Overloaded)
  716. ///
  717. /// The <see cref="OnDirPlacesReply"/> event is raised when a response is received from the simulator
  718. /// </summary>
  719. /// <param name="searchText">Search text</param>
  720. /// <param name="queryStart">Each request is limited to 100 places
  721. /// being returned. To get the first 100 result entries of a request use 0,
  722. /// from 100-199 use 1, 200-299 use 2, etc.</param>
  723. /// <returns>A UUID to correlate the results when the <see cref="OnDirPlacesReply"/> event is raised</returns>
  724. public UUID StartDirPlacesSearch(string searchText, int queryStart)
  725. {
  726. return StartDirPlacesSearch(searchText, DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeMature
  727. | DirFindFlags.IncludeAdult, ParcelCategory.Any, queryStart);
  728. }
  729. /// <summary>
  730. /// Queries the dataserver for parcels of land which are flagged to be shown in search
  731. ///
  732. /// The <see cref="OnDirPlacesReply"/> event is raised when a response is received from the simulator
  733. /// </summary>
  734. /// <param name="searchText">A string containing a list of keywords to search for separated by a space character</param>
  735. /// <param name="queryFlags">A set of flags which can be ORed to modify query options
  736. /// such as classified maturity rating.</param>
  737. /// <param name="category">The category to search</param>
  738. /// <param name="queryStart">Each request is limited to 100 places
  739. /// being returned. To get the first 100 result entries of a request use 0,
  740. /// from 100-199 use 1, 200-299 use 2, etc.</param>
  741. /// <returns>A UUID to correlate the results when the <see cref="OnDirPlacesReply"/> event is raised</returns>
  742. /// <example>
  743. /// Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult
  744. /// <code>
  745. /// UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0);
  746. /// </code>
  747. /// </example>
  748. /// <remarks>
  749. /// Additional information on the results can be obtained by using the ParcelManager.InfoRequest method
  750. /// </remarks>
  751. public UUID StartDirPlacesSearch(string searchText, DirFindFlags queryFlags, ParcelCategory category, int queryStart)
  752. {
  753. DirPlacesQueryPacket query = new DirPlacesQueryPacket();
  754. UUID queryID = UUID.Random();
  755. query.AgentData.AgentID = Client.Self.AgentID;
  756. query.AgentData.SessionID = Client.Self.SessionID;
  757. query.QueryData.Category = (sbyte)category;
  758. query.QueryData.QueryFlags = (uint)queryFlags;
  759. query.QueryData.QueryID = queryID;
  760. query.QueryData.QueryText = Utils.StringToBytes(searchText);
  761. query.QueryData.QueryStart = queryStart;
  762. query.QueryData.SimName = Utils.StringToBytes(string.Empty);
  763. Client.Network.SendPacket(query);
  764. return queryID;
  765. }
  766. /// <summary>
  767. /// Starts a search for land sales using the directory
  768. ///
  769. /// The <see cref="OnDirLandReply"/> event is raised when a response is received from the simulator
  770. /// </summary>
  771. /// <param name="typeFlags">What type of land to search for. Auction,
  772. /// estate, mainland, "first land", etc</param>
  773. /// <remarks>The OnDirLandReply event handler must be registered before
  774. /// calling this function. There is no way to determine how many
  775. /// results will be returned, or how many times the callback will be
  776. /// fired other than you won't get more than 100 total parcels from
  777. /// each query.</remarks>
  778. public void StartLandSearch(SearchTypeFlags typeFlags)
  779. {
  780. StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0);
  781. }
  782. /// <summary>
  783. /// Starts a search for land sales using the directory
  784. ///
  785. /// The <seealso cref="OnDirLandReply"/> event is raised when a response is received from the simulator
  786. /// </summary>
  787. /// <param name="typeFlags">What type of land to search for. Auction,
  788. /// estate, mainland, "first land", etc</param>
  789. /// <param name="priceLimit">Maximum price to search for</param>
  790. /// <param name="areaLimit">Maximum area to search for</param>
  791. /// <param name="queryStart">Each request is limited to 100 parcels
  792. /// being returned. To get the first 100 parcels of a request use 0,
  793. /// from 100-199 use 1, 200-299 use 2, etc.</param>
  794. /// <remarks>The OnDirLandReply event handler must be registered before
  795. /// calling this function. There is no way to determine how many
  796. /// results will be returned, or how many times the callback will be
  797. /// fired other than you won't get more than 100 total parcels from
  798. /// each query.</remarks>
  799. public void StartLandSearch(SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart)
  800. {
  801. StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByPrice |
  802. DirFindFlags.LimitByArea, typeFlags, priceLimit, areaLimit, queryStart);
  803. }
  804. /// <summary>
  805. /// Send a request to the data server for land sales listings
  806. /// </summary>
  807. ///
  808. /// <param name="findFlags">Flags sent to specify query options
  809. ///
  810. /// Available flags:
  811. /// Specify the parcel rating with one or more of the following:
  812. /// IncludePG IncludeMature IncludeAdult
  813. ///
  814. /// Specify the field to pre sort the results with ONLY ONE of the following:
  815. /// PerMeterSort NameSort AreaSort PricesSort
  816. ///
  817. /// Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order
  818. /// SortAsc
  819. ///
  820. /// Specify additional filters to limit the results with one or both of the following:
  821. /// LimitByPrice LimitByArea
  822. ///
  823. /// Flags can be combined by separating them with the | (pipe) character
  824. ///
  825. /// Additional details can be found in <see cref="DirFindFlags"/>
  826. /// </param>
  827. /// <param name="typeFlags">What type of land to search for. Auction,
  828. /// Estate or Mainland</param>
  829. /// <param name="priceLimit">Maximum price to search for when the
  830. /// DirFindFlags.LimitByPrice flag is specified in findFlags</param>
  831. /// <param name="areaLimit">Maximum area to search for when the
  832. /// DirFindFlags.LimitByArea flag is specified in findFlags</param>
  833. /// <param name="queryStart">Each request is limited to 100 parcels
  834. /// being returned. To get the first 100 parcels of a request use 0,
  835. /// from 100-199 use 100, 200-299 use 200, etc.</param>
  836. /// <remarks><para>The <seealso cref="OnDirLandReply"/> event will be raised with the response from the simulator
  837. ///
  838. /// There is no way to determine how many results will be returned, or how many times the callback will be
  839. /// fired other than you won't get more than 100 total parcels from
  840. /// each reply.</para>
  841. ///
  842. /// <para>Any land set for sale to either anybody or specific to the connected agent will be included in the
  843. /// results if the land is included in the query</para></remarks>
  844. /// <example>
  845. /// <code>
  846. /// // request all mainland, any maturity rating that is larger than 512 sq.m
  847. /// StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0);
  848. /// </code></example>
  849. public void StartLandSearch(DirFindFlags findFlags, SearchTypeFlags typeFlags, int priceLimit,
  850. int areaLimit, int queryStart)
  851. {
  852. DirLandQueryPacket query = new DirLandQueryPacket();
  853. query.AgentData.AgentID = Client.Self.AgentID;
  854. query.AgentData.SessionID = Client.Self.SessionID;
  855. query.QueryData.Area = areaLimit;
  856. query.QueryData.Price = priceLimit;
  857. query.QueryData.QueryStart = queryStart;
  858. query.QueryData.SearchType = (uint)typeFlags;
  859. query.QueryData.QueryFlags = (uint)findFlags;
  860. query.QueryData.QueryID = UUID.Random();
  861. Client.Network.SendPacket(query);
  862. }
  863. /// <summary>
  864. /// Search for Groups
  865. /// </summary>
  866. /// <param name="searchText">The name or portion of the name of the group you wish to search for</param>
  867. /// <param name="queryStart">Start from the match number</param>
  868. /// <returns></returns>
  869. public UUID StartGroupSearch(string searchText, int queryStart)
  870. {
  871. return StartGroupSearch(searchText, queryStart, DirFindFlags.Groups | DirFindFlags.IncludePG
  872. | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult);
  873. }
  874. /// <summary>
  875. /// Search for Groups
  876. /// </summary>
  877. /// <param name="searchText">The name or portion of the name of the group you wish to search for</param>
  878. /// <param name="queryStart">Start from the match number</param>
  879. /// <param name="flags">Search flags</param>
  880. /// <returns></returns>
  881. public UUID StartGroupSearch(string searchText, int queryStart, DirFindFlags flags)
  882. {
  883. DirFindQueryPacket find = new DirFindQueryPacket();
  884. find.AgentData.AgentID = Client.Self.AgentID;
  885. find.AgentData.SessionID = Client.Self.SessionID;
  886. find.QueryData.QueryFlags = (uint)flags;
  887. find.QueryData.QueryText = Utils.StringToBytes(searchText);
  888. find.QueryData.QueryID = UUID.Random();
  889. find.QueryData.QueryStart = queryStart;
  890. Client.Network.SendPacket(find);
  891. return find.QueryData.QueryID;
  892. }
  893. /// <summary>
  894. /// Search the People directory for other avatars
  895. /// </summary>
  896. /// <param name="searchText">The name or portion of the name of the avatar you wish to search for</param>
  897. /// <param name="queryStart"></param>
  898. /// <returns></returns>
  899. public UUID StartPeopleSearch(string searchText, int queryStart)
  900. {
  901. DirFindQueryPacket find = new DirFindQueryPacket();
  902. find.AgentData.AgentID = Client.Self.AgentID;
  903. find.AgentData.SessionID = Client.Self.SessionID;
  904. find.QueryData.QueryFlags = (uint)DirFindFlags.People;
  905. find.QueryData.QueryText = Utils.StringToBytes(searchText);
  906. find.QueryData.QueryID = UUID.Random();
  907. find.QueryData.QueryStart = queryStart;
  908. Client.Network.SendPacket(find);
  909. return find.QueryData.QueryID;
  910. }
  911. /// <summary>
  912. /// Search Places for parcels of land you personally own
  913. /// </summary>
  914. public UUID StartPlacesSearch()
  915. {
  916. return StartPlacesSearch(DirFindFlags.AgentOwned, ParcelCategory.Any, String.Empty, String.Empty,
  917. UUID.Zero, UUID.Random());
  918. }
  919. /// <summary>
  920. /// Searches Places for land owned by the specified group
  921. /// </summary>
  922. /// <param name="groupID">ID of the group you want to recieve land list for (You must be a member of the group)</param>
  923. /// <returns>Transaction (Query) ID which can be associated with results from your request.</returns>
  924. public UUID StartPlacesSearch(UUID groupID)
  925. {
  926. return StartPlacesSearch(DirFindFlags.GroupOwned, ParcelCategory.Any, String.Empty, String.Empty,
  927. groupID, UUID.Random());
  928. }
  929. /// <summary>
  930. /// Search the Places directory for parcels that are listed in search and contain the specified keywords
  931. /// </summary>
  932. /// <param name="searchText">A string containing the keywords to search for</param>
  933. /// <returns>Transaction (Query) ID which can be associated with results from your request.</returns>
  934. public UUID StartPlacesSearch(string searchText)
  935. {
  936. return StartPlacesSearch(DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult,
  937. ParcelCategory.Any, searchText, String.Empty, UUID.Zero, UUID.Random());
  938. }
  939. /// <summary>
  940. /// Search Places - All Options
  941. /// </summary>
  942. /// <param name="findFlags">One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc.</param>
  943. /// <param name="searchCategory">One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer</param>
  944. /// <param name="searchText">A string containing a list of keywords to search for separated by a space character</param>
  945. /// <param name="simulatorName">String Simulator Name to search in</param>
  946. /// <param name="groupID">LLUID of group you want to recieve results for</param>
  947. /// <param name="transactionID">Transaction (Query) ID which can be associated with results from your request.</param>
  948. /// <returns>Transaction (Query) ID which can be associated with results from your request.</returns>
  949. public UUID StartPlacesSearch(DirFindFlags findFlags, ParcelCategory searchCategory, string searchText, string simulatorName,
  950. UUID groupID, UUID transactionID)
  951. {
  952. PlacesQueryPacket find = new PlacesQueryPacket();
  953. find.AgentData.AgentID = Client.Self.AgentID;
  954. find.AgentData.SessionID = Client.Self.SessionID;
  955. find.AgentData.QueryID = groupID;
  956. find.TransactionData.TransactionID = transactionID;
  957. find.QueryData.QueryText = Utils.StringToBytes(searchText);
  958. find.QueryData.QueryFlags = (uint)findFlags;
  959. find.QueryData.Category = (sbyte)searchCategory;
  960. find.QueryData.SimName = Utils.StringToBytes(simulatorName);
  961. Client.Network.SendPacket(find);
  962. return transactionID;
  963. }
  964. /// <summary>
  965. /// Search All Events with specifid searchText in all categories, includes PG, Mature and Adult
  966. /// </summary>
  967. /// <param name="searchText">A string containing a list of…

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