diff --git a/OpenMetaverse/DirectoryManager.cs b/OpenMetaverse/DirectoryManager.cs index a05d0960..2986bc2d 100644 --- a/OpenMetaverse/DirectoryManager.cs +++ b/OpenMetaverse/DirectoryManager.cs @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2008, openmetaverse.org + * Copyright (c) 2006-2009, openmetaverse.org * All rights reserved. * * - Redistribution and use in source and binary forms, with or without @@ -25,8 +25,8 @@ */ using System; -using System.Collections.Generic; using System.Threading; +using System.Collections.Generic; using OpenMetaverse.Packets; using OpenMetaverse.Interfaces; using OpenMetaverse.Messages.Linden; @@ -34,13 +34,12 @@ using OpenMetaverse.Messages.Linden; namespace OpenMetaverse { /// - /// Access to the dataserver which allows searching for land, events, people, etc + /// Access to the data server which allows searching for land, events, people, etc /// public class DirectoryManager { - /// - /// The different categories a classified ad can be placed in - /// + #region Enums + /// Classified Ad categories public enum ClassifiedCategories { /// Classified is listed in the Any category @@ -65,7 +64,7 @@ namespace OpenMetaverse Personal } - /// + /// Event Categories public enum EventCategories { /// @@ -94,36 +93,10 @@ namespace OpenMetaverse Miscellaneous = 29 } - // I can be deleted as soon as the flags for DirLandQuery can be verified to not use - // the below listed combinations. e.g: PgSimsOnly *should not* be necessary any longer as it looks redundant - // -- Jim - // - // - // Modifier flags sent to DirectoryManager to change the behavior of the - // query - // - // Land Search Flags required in addition to specify land maturity rating: - // - // PgSimsOnly | SortAsc | PerMeterSort | IncludePG | IncludeAdult - // would sort the results ascending, sort by sale price/m2, Include only Adult and PG Land - // in the search results. - // - // - // Desired QueryRequired Flags - // PGPgSimsOnly | IncludePG - // PG+MatureIncludePG | IncludeMature - // PG+Mature+AdultIncludePG | IncludeMature | IncludeAdult - // Mature+AdultMatureSimsOnly | IncludeMature | IncludeAdult - // AdultIncludeAdult - // MatureMatureSimsOnly | IncludeMature - // PG+AdultPgSimsOnly | IncludePG | IncludeAdult - // - - /// /// Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. /// - /// Flags can be combined using the | (pipe) character + /// Flags can be combined using the | (pipe) character, not all flags are available in all queries /// [Flags] public enum DirFindFlags @@ -137,7 +110,7 @@ namespace OpenMetaverse //Places = 1 << 2, /// Events = 1 << 3, - /// + /// Query the Groups database Groups = 1 << 4, /// Query the Events database DateEvents = 1 << 5, @@ -193,7 +166,7 @@ namespace OpenMetaverse /// Include Adult land in results. This flag is used when searching both the Events and Land sales databases IncludeAdult = 1 << 26, /// - AdultOnly = 1 << 27 + AdultOnly = 1 << 27 } /// @@ -204,8 +177,6 @@ namespace OpenMetaverse { /// Search Auction, Mainland and Estate Any = -1, - /// Do not search - None = 0, /// Land which is currently up for auction Auction = 1 << 1, // Land available to new landowners (formerly the FirstLand program) @@ -230,6 +201,51 @@ namespace OpenMetaverse Adult = 2 } + /// + /// Classified Ad Options + /// + /// There appear to be two formats the flags are packed in. + /// This set of flags is for the newer style + [Flags] + public enum ClassifiedFlags : byte + { + None = 1 << 0, + Mature = 1 << 1, + Enabled = 1 << 2, + // HasPrice = 1 << 3, // Deprecated + UpdateTime = 1 << 4, + AutoRenew = 1 << 5 + } + + /// + /// Classified ad query options + /// + [Flags] + public enum ClassifiedQueryFlags + { + /// Include all ads in results + All = PG | Mature | Adult, + /// Include PG ads in results + PG = 1 << 2, + /// Include Mature ads in results + Mature = 1 << 3, + /// Include Adult ads in results + Adult = 1 << 6, + } + + /// + /// The For Sale flag in PlacesReplyData + /// + public enum PlacesFlags : byte + { + /// Parcel is not listed for sale + NotForSale = 0, + /// Parcel is For Sale + ForSale = 128 + } + + #endregion + #region Structs /// /// A classified ad on the grid /// @@ -249,49 +265,14 @@ namespace OpenMetaverse /// Price that was paid for this ad public int Price; - /// - /// Display a classified ad in a one line human readable format - /// - /// A string representing a single classified ad + /// Print the struct data as a string + /// A string containing the field name, and field value public override string ToString() { - return String.Format("Classified Ad: ID: {0}, Name: {1}, Flags: [{2}] {3}, Created: {4}, Expires: {5}, Paid: {6}", - this.ID, this.Name, this.Flags, this.Flags.ToString(), this.CreationDate, this.ExpirationDate, this.Price); + return Helpers.StructToString(this); } } - /// - /// Classified Ad Options - /// - /// There appear to be two formats the flags are packed in. - /// This set of flags is for the newer style - [Flags] - public enum ClassifiedFlags : byte - { - None = 1 << 0, - Mature = 1 << 1, - Enabled = 1 << 2, - // HasPrice = 1 << 3, // Deprecated - UpdateTime = 1 << 4, - AutoRenew = 1 << 5 - } - - /// - /// Classified ad query options - /// - [Flags] - public enum ClassifiedQueryFlags - { - /// Include all ads in results - All = PG | Mature | Adult, - /// Include PG ads in results - PG = 1 << 2, - /// Include Mature ads in results - Mature = 1 << 3, - /// Include Adult ads in results - Adult = 1 << 6, - } - /// /// A parcel retrieved from the dataserver such as results from the /// "For-Sale" listings or "Places" Search @@ -317,14 +298,11 @@ namespace OpenMetaverse /// Parcel traffic public float Dwell; - /// - /// Display an entry in a one line human readable format - /// - /// A string representing a single parcel entry + /// Print the struct data as a string + /// A string containing the field name, and field value public override string ToString() - { - return String.Format("Parcel ID: {0}, Name: {1}, Area: {2}, Price: {3}, IsAuction: {4}, IsForSale: {5}, Dwell: {6}" + System.Environment.NewLine, - this.ID, this.Name, this.ActualArea, this.SalePrice, this.Auction, this.ForSale, this.Dwell); + { + return Helpers.StructToString(this); } } @@ -334,13 +312,21 @@ namespace OpenMetaverse public struct AgentSearchData { /// Online status of agent + /// This field appears to be obsolete and always returns false public bool Online; - /// Agents first name + /// The agents first name public string FirstName; - /// Agents last name + /// The agents last name public string LastName; - /// Agents + /// The agents public UUID AgentID; + + /// Print the struct data as a string + /// A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } } /// @@ -348,147 +334,364 @@ namespace OpenMetaverse /// public struct GroupSearchData { + /// The Group ID public UUID GroupID; + /// The name of the group public string GroupName; + /// The current number of members public int Members; + + /// Print the struct data as a string + /// A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } } /// - /// Response to a "Places" Search, e.g. My Land, Group Land, etc. - /// Note: This is not DirPlacesReply + /// Parcel information returned from a request + /// + /// Represents one of the following: + /// A parcel of land on the grid that has its Show In Search flag set + /// A parcel of land owned by the agent making the request + /// A parcel of land owned by a group the agent making the request is a member of + /// + /// + /// In a request for Group Land, the First record will contain an empty record + /// + /// Note: This is not the same as searching the land for sale data source /// public struct PlacesSearchData { + /// The ID of the Agent of Group that owns the parcel public UUID OwnerID; + /// The name public string Name; + /// The description public string Desc; + /// The Size of the parcel public int ActualArea; + /// The billable Size of the parcel, for mainland + /// parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller + /// than the ActualArea. For Estate land this will always be 0 public int BillableArea; - public byte Flags; + /// Indicates the ForSale status of the parcel + public PlacesFlags Flags; + /// The Gridwide X position public float GlobalX; + /// The Gridwide Y position public float GlobalY; + /// The Z position of the parcel, or 0 if no landing point set public float GlobalZ; + /// The name of the Region the parcel is located in public string SimName; + /// The Asset ID of the parcels Snapshot texture public UUID SnapshotID; + /// The calculated visitor traffic public float Dwell; + /// The billing product SKU + /// Known values are: + /// + /// 023Mainland / Full Region + /// 024Estate / Full Region + /// 027Estate / Openspace + /// 029Estate / Homestead + /// 129Mainland / Homestead (Linden Owned) + /// + /// + public string SKU; + /// No longer used, will always be 0 public int Price; + + /// Get a SL URL for the parcel + /// A string, containing a standard SLURL + public string ToSLurl() + { + float x, y; + Helpers.GlobalPosToRegionHandle(this.GlobalX, this.GlobalY, out x, out y); + return "secondlife://" + this.SimName + "/" + x + "/" + y + "/" + this.GlobalZ; + } + + /// Print the struct data as a string + /// A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } } /// - /// Response to "Events" search + /// An "Event" Listing summary /// public struct EventsSearchData { + /// The ID of the event creator public UUID Owner; + /// The name of the event public string Name; + /// The events ID public uint ID; + /// A string containing the short date/time the event will begin public string Date; + /// The event start time in Unixtime (seconds since epoch) public uint Time; + /// The events maturity rating public EventFlags Flags; + + /// Print the struct data as a string + /// A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } } /// - /// an Event returned from the dataserver + /// The details of an "Event" /// public struct EventInfo { + /// The events ID public uint ID; + /// The ID of the event creator public UUID Creator; + /// The name of the event public string Name; + /// The category public EventCategories Category; + /// The events description public string Desc; + /// The short date/time the event will begin public string Date; - public UInt32 DateUTC; - public UInt32 Duration; - public UInt32 Cover; - public UInt32 Amount; + /// The event start time in Unixtime (seconds since epoch) UTC adjusted + public uint DateUTC; + /// The length of the event in minutes + public uint Duration; + /// 0 if no cover charge applies + public uint Cover; + /// The cover charge amount in L$ if applicable + public uint Amount; + /// The name of the region where the event is being held public string SimName; + /// The gridwide location of the event public Vector3d GlobalPos; + /// The maturity rating public EventFlags Flags; + + /// Get a SL URL for the parcel where the event is hosted + /// A string, containing a standard SLURL + public string ToSLurl() + { + float x, y; + Helpers.GlobalPosToRegionHandle((float)this.GlobalPos.X, (float)this.GlobalPos.Y, out x, out y); + return "secondlife://" + this.SimName + "/" + x + "/" + y + "/" + this.GlobalPos.Z; + } + + /// Print the struct data as a string + /// A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } } - /// - /// - /// - /// - public delegate void ClassifiedReplyCallback(List classifieds); - /// - /// - /// - /// - public delegate void DirLandReplyCallback(List dirParcels); + #endregion Structs + + #region Event delegates, Raise Events + + /// The event subscribers. null if no subcribers + private EventHandler m_EventInfoReply; - /// - /// - /// - /// - /// - public delegate void DirPeopleReplyCallback(UUID queryID, List matchedPeople); + /// Raises the EventInfoReply event + /// An EventInfoReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnEventInfo(EventInfoReplyEventArgs e) + { + EventHandler handler = m_EventInfoReply; + if (handler != null) + handler(this, e); + } - /// - /// - /// - /// - /// - public delegate void DirGroupsReplyCallback(UUID queryID, List matchedGroups); + /// Thread sync lock object + private readonly object m_EventDetailLock = new object(); - /// - /// Passes results of search -> places - /// - /// UUID of this request - /// List of parcels found in search - public delegate void DirPlacesReplyCallback(UUID queryID, List matchedParcels); + /// Raised when the data server responds to a request. + public event EventHandler EventInfoReply + { + add { lock (m_EventDetailLock) { m_EventInfoReply += value; } } + remove { lock (m_EventDetailLock) { m_EventInfoReply -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirEvents; + /// Raises the DirEventsReply event + /// An DirEventsReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirEvents(DirEventsReplyEventArgs e) + { + EventHandler handler = m_DirEvents; + if (handler != null) + handler(this, e); + } - /// - /// - /// - /// - /// - public delegate void PlacesReplyCallback(UUID queryID, List matchedPlaces); + /// Thread sync lock object + private readonly object m_DirEventsLock = new object(); - /// - /// - /// - /// - /// - public delegate void EventReplyCallback(UUID queryID, List matchedEvents); + /// Raised when the data server responds to a request. + public event EventHandler DirEventsReply + { + add { lock (m_DirEventsLock) { m_DirEvents += value; } } + remove { lock (m_DirEventsLock) { m_DirEvents -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_Places; - /// - /// - /// - /// - public delegate void EventInfoCallback(EventInfo matchedEvent); + /// Raises the PlacesReply event + /// A PlacesReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnPlaces(PlacesReplyEventArgs e) + { + EventHandler handler = m_Places; + if (handler != null) + handler(this, e); + } - /// - /// - /// - public event ClassifiedReplyCallback OnClassifiedReply; - /// - /// - /// - public event DirLandReplyCallback OnDirLandReply; + /// Thread sync lock object + private readonly object m_PlacesLock = new object(); - public event DirPeopleReplyCallback OnDirPeopleReply; + /// Raised when the data server responds to a request. + public event EventHandler PlacesReply + { + add { lock (m_PlacesLock) { m_Places += value; } } + remove { lock (m_PlacesLock) { m_Places -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirPlaces; - public event DirGroupsReplyCallback OnDirGroupsReply; + /// Raises the DirPlacesReply event + /// A DirPlacesReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirPlaces(DirPlacesReplyEventArgs e) + { + EventHandler handler = m_DirPlaces; + if (handler != null) + handler(this, e); + } - /// - /// When we have result of search->places - /// - public event DirPlacesReplyCallback OnDirPlacesReply; + /// Thread sync lock object + private readonly object m_DirPlacesLock = new object(); - public event PlacesReplyCallback OnPlacesReply; + /// Raised when the data server responds to a request. + public event EventHandler DirPlacesReply + { + add { lock (m_DirPlacesLock) { m_DirPlaces += value; } } + remove { lock (m_DirPlacesLock) { m_DirPlaces -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirClassifieds; - // List of Events - public event EventReplyCallback OnEventsReply; + /// Raises the DirClassifiedsReply event + /// A DirClassifiedsReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirClassifieds(DirClassifiedsReplyEventArgs e) + { + EventHandler handler = m_DirClassifieds; + if (handler != null) + handler(this, e); + } - // Event Details - public event EventInfoCallback OnEventInfo; + /// Thread sync lock object + private readonly object m_DirClassifiedsLock = new object(); + /// Raised when the data server responds to a request. + public event EventHandler DirClassifiedsReply + { + add { lock (m_DirClassifiedsLock) { m_DirClassifieds += value; } } + remove { lock (m_DirClassifiedsLock) { m_DirClassifieds -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirGroups; + + /// Raises the DirGroupsReply event + /// A DirGroupsReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirGroups(DirGroupsReplyEventArgs e) + { + EventHandler handler = m_DirGroups; + if (handler != null) + handler(this, e); + } + + /// Thread sync lock object + private readonly object m_DirGroupsLock = new object(); + + /// Raised when the data server responds to a request. + public event EventHandler DirGroupsReply + { + add { lock (m_DirGroupsLock) { m_DirGroups += value; } } + remove { lock (m_DirGroupsLock) { m_DirGroups -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirPeople; + + /// Raises the DirPeopleReply event + /// A DirPeopleReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirPeople(DirPeopleReplyEventArgs e) + { + EventHandler handler = m_DirPeople; + if (handler != null) + handler(this, e); + } + + /// Thread sync lock object + private readonly object m_DirPeopleLock = new object(); + + /// Raised when the data server responds to a request. + public event EventHandler DirPeopleReply + { + add { lock (m_DirPeopleLock) { m_DirPeople += value; } } + remove { lock (m_DirPeopleLock) { m_DirPeople -= value; } } + } + + /// The event subscribers. null if no subcribers + private EventHandler m_DirLandReply; + + /// Raises the DirLandReply event + /// A DirLandReplyEventArgs object containing the + /// data returned from the data server + protected virtual void OnDirLand(DirLandReplyEventArgs e) + { + EventHandler handler = m_DirLandReply; + if (handler != null) + handler(this, e); + } + + /// Thread sync lock object + private readonly object m_DirLandLock = new object(); + + /// Raised when the data server responds to a request. + public event EventHandler DirLandReply + { + add { lock (m_DirLandLock) { m_DirLandReply += value; } } + remove { lock (m_DirLandLock) { m_DirLandReply -= value; } } + } + + #endregion + + #region Private Members private GridClient Client; + #endregion + #region Constructors /// /// Constructs a new instance of the DirectoryManager class /// @@ -496,7 +699,7 @@ namespace OpenMetaverse public DirectoryManager(GridClient client) { Client = client; - + Client.Network.RegisterCallback(PacketType.DirClassifiedReply, new NetworkManager.PacketCallback(DirClassifiedReplyHandler)); // Deprecated, replies come in over capabilities Client.Network.RegisterCallback(PacketType.DirLandReply, new NetworkManager.PacketCallback(DirLandReplyHandler)); @@ -511,6 +714,9 @@ namespace OpenMetaverse Client.Network.RegisterCallback(PacketType.DirPlacesReply, new NetworkManager.PacketCallback(DirPlacesReplyHandler)); } + #endregion + + #region Public Methods // Obsoleted due to new Adult search option [Obsolete("Use Overload with ClassifiedQueryFlags option instead")] public UUID StartClassifiedSearch(string searchText, ClassifiedCategories category, bool mature) @@ -532,7 +738,7 @@ namespace OpenMetaverse /// A UUID to correlate the results when the event is raised public UUID StartClassifiedSearch(string searchText) { - return StartClassifiedSearch(searchText, ClassifiedCategories.Any, ClassifiedQueryFlags.All); + return StartClassifiedSearch(searchText, ClassifiedCategories.Any, ClassifiedQueryFlags.All); } /// @@ -556,7 +762,7 @@ namespace OpenMetaverse /// the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received /// public UUID StartClassifiedSearch(string searchText, ClassifiedCategories category, ClassifiedQueryFlags queryFlags) - { + { DirClassifiedQueryPacket query = new DirClassifiedQueryPacket(); UUID queryID = UUID.Random(); @@ -612,11 +818,11 @@ namespace OpenMetaverse /// Additional information on the results can be obtained by using the ParcelManager.InfoRequest method /// public UUID StartDirPlacesSearch(string searchText, DirFindFlags queryFlags, ParcelCategory category, int queryStart) - { + { DirPlacesQueryPacket query = new DirPlacesQueryPacket(); - + UUID queryID = UUID.Random(); - + query.AgentData.AgentID = Client.Self.AgentID; query.AgentData.SessionID = Client.Self.SessionID; @@ -640,17 +846,15 @@ namespace OpenMetaverse /// The event is raised when a response is received from the simulator /// /// What type of land to search for. Auction, - /// estate, mainland, "first land", etc - /// A unique identifier that can identify packets associated - /// with this query from other queries + /// estate, mainland, "first land", etc /// The OnDirLandReply event handler must be registered before /// calling this function. There is no way to determine how many /// results will be returned, or how many times the callback will be /// fired other than you won't get more than 100 total parcels from /// each query. - public UUID StartLandSearch(SearchTypeFlags typeFlags) + public void StartLandSearch(SearchTypeFlags typeFlags) { - return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0); + StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0); } /// @@ -664,22 +868,20 @@ namespace OpenMetaverse /// Maximum area to search for /// Each request is limited to 100 parcels /// being returned. To get the first 100 parcels of a request use 0, - /// from 100-199 use 1, 200-299 use 2, etc. - /// A unique identifier that can identify packets associated - /// with this query from other queries + /// from 100-199 use 1, 200-299 use 2, etc. /// The OnDirLandReply event handler must be registered before /// calling this function. There is no way to determine how many /// results will be returned, or how many times the callback will be /// fired other than you won't get more than 100 total parcels from /// each query. - public UUID StartLandSearch(SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart) + public void StartLandSearch(SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart) { - return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByPrice | + StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByPrice | DirFindFlags.LimitByArea, typeFlags, priceLimit, areaLimit, queryStart); } /// - /// Request land listed for public sale + /// Send a request to the data server for land sales listings /// /// /// Flags sent to specify query options @@ -710,8 +912,6 @@ namespace OpenMetaverse /// Each request is limited to 100 parcels /// being returned. To get the first 100 parcels of a request use 0, /// from 100-199 use 100, 200-299 use 200, etc. - /// A unique identifier that can identify packets associated - /// with this query from other queries /// The event will be raised with the response from the simulator /// /// There is no way to determine how many results will be returned, or how many times the callback will be @@ -725,11 +925,9 @@ namespace OpenMetaverse /// // request all mainland, any maturity rating that is larger than 512 sq.m /// StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); /// - public UUID StartLandSearch(DirFindFlags findFlags, SearchTypeFlags typeFlags, int priceLimit, + public void StartLandSearch(DirFindFlags findFlags, SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart) { - UUID queryID = UUID.Random(); - DirLandQueryPacket query = new DirLandQueryPacket(); query.AgentData.AgentID = Client.Self.AgentID; query.AgentData.SessionID = Client.Self.SessionID; @@ -738,124 +936,82 @@ namespace OpenMetaverse query.QueryData.QueryStart = queryStart; query.QueryData.SearchType = (uint)typeFlags; query.QueryData.QueryFlags = (uint)findFlags; - query.QueryData.QueryID = queryID; + query.QueryData.QueryID = UUID.Random(); - Client.Network.SendPacket(query); - - return queryID; + Client.Network.SendPacket(query); } - + /// - /// Starts a search for a Group in the directory manager + /// Search for Groups /// - /// - /// A string containing a list of keywords to search for separated by a space character - /// Each request is limited to 100 parcels - /// being returned. To get the first 100 parcels of a request use 0, - /// from 100-199 use 100, 200-299 use 200, etc. - /// A unique identifier that can identify packets associated - /// with this query from other queries - /// The OnDirLandReply event handler must be registered before - /// calling this function. There is no way to determine how many - /// results will be returned, or how many times the callback will be - /// fired other than you won't get more than 100 total parcels from - /// each query. - public UUID StartGroupSearch(DirFindFlags findFlags, string searchText, int queryStart) - { - return StartGroupSearch(findFlags, searchText, queryStart, UUID.Random()); - } - - /// - /// Search for groups - /// - /// - /// + /// The name or portion of the name of the group you wish to search for /// - /// /// - public UUID StartGroupSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID) + public UUID StartGroupSearch(string searchText, int queryStart) { DirFindQueryPacket find = new DirFindQueryPacket(); find.AgentData.AgentID = Client.Self.AgentID; find.AgentData.SessionID = Client.Self.SessionID; - find.QueryData.QueryFlags = (uint)findFlags; + find.QueryData.QueryFlags = (uint)DirFindFlags.Groups; find.QueryData.QueryText = Utils.StringToBytes(searchText); - find.QueryData.QueryID = queryID; + find.QueryData.QueryID = UUID.Random(); find.QueryData.QueryStart = queryStart; + Client.Network.SendPacket(find); - return queryID; - } + return find.QueryData.QueryID; + } + /// - /// Search the people directory for other avatars - /// - /// The event is raised when a response is received from the simulator + /// Search the People directory for other avatars /// - /// - /// A string containing a list of keywords to search for separated by a space character + /// The name or portion of the name of the avatar you wish to search for /// /// - public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart) - { - return StartPeopleSearch(findFlags, searchText, queryStart, UUID.Random()); - } - - /// - /// - /// - /// - /// A string containing a list of keywords to search for separated by a space character - /// - /// - /// - public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID) + public UUID StartPeopleSearch(string searchText, int queryStart) { DirFindQueryPacket find = new DirFindQueryPacket(); find.AgentData.AgentID = Client.Self.AgentID; find.AgentData.SessionID = Client.Self.SessionID; - find.QueryData.QueryFlags = (uint)findFlags; + find.QueryData.QueryFlags = (uint)DirFindFlags.People; find.QueryData.QueryText = Utils.StringToBytes(searchText); - find.QueryData.QueryID = queryID; + find.QueryData.QueryID = UUID.Random(); find.QueryData.QueryStart = queryStart; Client.Network.SendPacket(find); - return queryID; + return find.QueryData.QueryID; } - + /// - /// Search "places" for parcels of land you personally own + /// Search Places for parcels of land you personally own /// public UUID StartPlacesSearch() { return StartPlacesSearch(DirFindFlags.AgentOwned, ParcelCategory.Any, String.Empty, String.Empty, - UUID.Zero, UUID.Zero); + UUID.Zero, UUID.Random()); } /// - /// Searches Places for Land owned by a specific user or group + /// Searches Places for land owned by the specified group /// - /// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - /// LLUID of group you want to recieve land list for (You must be in group), or - /// LLUID.Zero for Your own land + /// ID of the group you want to recieve land list for (You must be a member of the group) /// Transaction (Query) ID which can be associated with results from your request. - public UUID StartPlacesSearch(DirFindFlags findFlags, UUID groupID) + public UUID StartPlacesSearch(UUID groupID) { - return StartPlacesSearch(findFlags, ParcelCategory.Any, String.Empty, String.Empty, groupID, - UUID.Random()); + return StartPlacesSearch(DirFindFlags.GroupOwned, ParcelCategory.Any, String.Empty, String.Empty, + groupID, UUID.Random()); } /// - /// Search Places + /// Search the Places directory for parcels that are listed in search and contain the specified keywords /// - /// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - /// One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer - /// UUID of group you want to recieve results for - /// Transaction (Query) ID which can be associated with results from your request. + /// A string containing the keywords to search for /// Transaction (Query) ID which can be associated with results from your request. - public UUID StartPlacesSearch(DirFindFlags findFlags, ParcelCategory searchCategory, UUID groupID, UUID transactionID) + public UUID StartPlacesSearch(string searchText) { - return StartPlacesSearch(findFlags, searchCategory, String.Empty, String.Empty, groupID, transactionID); + return StartPlacesSearch(DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, + ParcelCategory.Any, searchText, String.Empty, UUID.Zero, UUID.Random()); } /// @@ -868,7 +1024,8 @@ namespace OpenMetaverse /// LLUID of group you want to recieve results for /// Transaction (Query) ID which can be associated with results from your request. /// Transaction (Query) ID which can be associated with results from your request. - public UUID StartPlacesSearch(DirFindFlags findFlags, ParcelCategory searchCategory, string searchText, string simulatorName, UUID groupID, UUID transactionID) + public UUID StartPlacesSearch(DirFindFlags findFlags, ParcelCategory searchCategory, string searchText, string simulatorName, + UUID groupID, UUID transactionID) { PlacesQueryPacket find = new PlacesQueryPacket(); find.AgentData.AgentID = Client.Self.AgentID; @@ -886,7 +1043,6 @@ namespace OpenMetaverse return transactionID; } - /// /// Search All Events with specifid searchText in all categories, includes PG, Mature and Adult /// @@ -897,7 +1053,8 @@ namespace OpenMetaverse /// UUID of query to correlate results in callback. public UUID StartEventsSearch(string searchText, uint queryStart) { - return StartEventsSearch(searchText, DirFindFlags.DateEvents | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, "u", queryStart, EventCategories.All); + return StartEventsSearch(searchText, DirFindFlags.DateEvents | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, + "u", queryStart, EventCategories.All); } /// @@ -931,9 +1088,9 @@ namespace OpenMetaverse Client.Network.SendPacket(find); return queryID; } - + /// Requests Event Details - /// ID of Event returned from Places Search + /// ID of Event returned from the method public void EventInfoRequest(uint eventID) { EventInfoRequestPacket find = new EventInfoRequestPacket(); @@ -944,7 +1101,7 @@ namespace OpenMetaverse Client.Network.SendPacket(find); } - + #endregion #region Blocking Functions @@ -953,23 +1110,24 @@ namespace OpenMetaverse int timeoutMS, out List results) { AutoResetEvent searchEvent = new AutoResetEvent(false); - UUID id = UUID.Random(); + UUID id = UUID.Zero; List people = null; - DirPeopleReplyCallback callback = - delegate(UUID queryid, List matches) + EventHandler callback = + delegate(object sender, DirPeopleReplyEventArgs e) { - if (id == queryid) + if (id == e.QueryID) { - people = matches; + people = e.MatchedPeople; searchEvent.Set(); } }; - OnDirPeopleReply += callback; - StartPeopleSearch(findFlags, searchText, queryStart, id); + DirPeopleReply += callback; + + id = StartPeopleSearch(searchText, queryStart); searchEvent.WaitOne(timeoutMS, false); - OnDirPeopleReply -= callback; + DirPeopleReply -= callback; results = people; return (results != null); @@ -979,9 +1137,12 @@ namespace OpenMetaverse #region Packet Handlers - private void DirClassifiedReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void DirClassifiedReplyHandler(Packet packet, Simulator simulator) { - if (OnClassifiedReply != null) + if (m_DirClassifieds != null) { DirClassifiedReplyPacket reply = (DirClassifiedReplyPacket)packet; List classifieds = new List(); @@ -1000,14 +1161,16 @@ namespace OpenMetaverse classifieds.Add(classified); } - try { OnClassifiedReply(classifieds); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnDirClassifieds(new DirClassifiedsReplyEventArgs(classifieds)); } } - private void DirLandReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void DirLandReplyHandler(Packet packet, Simulator simulator) { - if (OnDirLandReply != null) + if (m_DirLandReply != null) { List parcelsForSale = new List(); DirLandReplyPacket reply = (DirLandReplyPacket)packet; @@ -1025,15 +1188,17 @@ namespace OpenMetaverse parcelsForSale.Add(dirParcel); } - - try { OnDirLandReply(parcelsForSale); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnDirLand(new DirLandReplyEventArgs(parcelsForSale)); } } - private void DirLandReplyEventHandler(string capsKey, IMessage message, Simulator simulator) + /// Process an incoming event message + /// The Unique Capabilities Key + /// The event message containing the data + /// The simulator the message originated from + protected void DirLandReplyEventHandler(string capsKey, IMessage message, Simulator simulator) { - if (OnDirLandReply != null) + if (m_DirLandReply != null) { List parcelsForSale = new List(); @@ -1053,14 +1218,16 @@ namespace OpenMetaverse parcelsForSale.Add(dirParcel); } - try { OnDirLandReply(parcelsForSale); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnDirLand(new DirLandReplyEventArgs(parcelsForSale)); } } + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from protected void DirPeopleReplyHandler(Packet packet, Simulator simulator) { - if (OnDirPeopleReply != null) + if (m_DirPeople != null) { DirPeopleReplyPacket peopleReply = packet as DirPeopleReplyPacket; List matches = new List(peopleReply.QueryReplies.Length); @@ -1073,16 +1240,19 @@ namespace OpenMetaverse searchData.AgentID = reply.AgentID; matches.Add(searchData); } - try { OnDirPeopleReply(peopleReply.QueryData.QueryID, matches); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + + OnDirPeople(new DirPeopleReplyEventArgs(peopleReply.QueryData.QueryID, matches)); } } + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from protected void DirGroupsReplyHandler(Packet packet, Simulator simulator) { - if (OnDirGroupsReply != null) + if (m_DirGroups != null) { - DirGroupsReplyPacket groupsReply = packet as DirGroupsReplyPacket; + DirGroupsReplyPacket groupsReply = (DirGroupsReplyPacket)packet; List matches = new List(groupsReply.QueryReplies.Length); foreach (DirGroupsReplyPacket.QueryRepliesBlock reply in groupsReply.QueryReplies) { @@ -1092,14 +1262,18 @@ namespace OpenMetaverse groupsData.Members = reply.Members; matches.Add(groupsData); } - try { OnDirGroupsReply(groupsReply.QueryData.QueryID, matches); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + + OnDirGroups(new DirGroupsReplyEventArgs(groupsReply.QueryData.QueryID, matches)); } } - private void PlacesReplyEventHandler(string capsKey, IMessage message, Simulator simulator) + /// Process an incoming event message + /// The Unique Capabilities Key + /// The event message containing the data + /// The simulator the message originated from + protected void PlacesReplyEventHandler(string capsKey, IMessage message, Simulator simulator) { - if (OnPlacesReply != null) + if (m_Places != null) { PlacesReplyMessage replyMessage = (PlacesReplyMessage)message; List places = new List(); @@ -1111,7 +1285,7 @@ namespace OpenMetaverse place.BillableArea = replyMessage.QueryDataBlocks[i].BillableArea; place.Desc = replyMessage.QueryDataBlocks[i].Description; place.Dwell = replyMessage.QueryDataBlocks[i].Dwell; - place.Flags = (byte)replyMessage.QueryDataBlocks[i].Flags; + place.Flags = (DirectoryManager.PlacesFlags)(byte)replyMessage.QueryDataBlocks[i].Flags; place.GlobalX = replyMessage.QueryDataBlocks[i].GlobalX; place.GlobalY = replyMessage.QueryDataBlocks[i].GlobalY; place.GlobalZ = replyMessage.QueryDataBlocks[i].GlobalZ; @@ -1120,17 +1294,20 @@ namespace OpenMetaverse place.Price = replyMessage.QueryDataBlocks[i].Price; place.SimName = replyMessage.QueryDataBlocks[i].SimName; place.SnapshotID = replyMessage.QueryDataBlocks[i].SnapShotID; + place.SKU = replyMessage.QueryDataBlocks[i].ProductSku; places.Add(place); } - try { OnPlacesReply(replyMessage.TransactionID, places); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnPlaces(new PlacesReplyEventArgs(replyMessage.QueryID, places)); } } - private void PlacesReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void PlacesReplyHandler(Packet packet, Simulator simulator) { - if (OnPlacesReply != null) + if (m_Places != null) { PlacesReplyPacket placesReply = packet as PlacesReplyPacket; List places = new List(); @@ -1143,7 +1320,7 @@ namespace OpenMetaverse place.Desc = Utils.BytesToString(block.Desc); place.ActualArea = block.ActualArea; place.BillableArea = block.BillableArea; - place.Flags = block.Flags; + place.Flags = (PlacesFlags)block.Flags; place.GlobalX = block.GlobalX; place.GlobalY = block.GlobalY; place.GlobalZ = block.GlobalZ; @@ -1154,16 +1331,19 @@ namespace OpenMetaverse places.Add(place); } - try { OnPlacesReply(placesReply.TransactionData.TransactionID, places); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + + OnPlaces(new PlacesReplyEventArgs(placesReply.TransactionData.TransactionID, places)); } } - private void EventsReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void EventsReplyHandler(Packet packet, Simulator simulator) { - if (OnEventsReply != null) + if (m_DirEvents != null) { - DirEventsReplyPacket eventsReply = packet as DirEventsReplyPacket; + DirEventsReplyPacket eventsReply = (DirEventsReplyPacket)packet; List matches = new List(eventsReply.QueryReplies.Length); foreach (DirEventsReplyPacket.QueryRepliesBlock reply in eventsReply.QueryReplies) @@ -1178,14 +1358,16 @@ namespace OpenMetaverse matches.Add(eventsData); } - try { OnEventsReply(eventsReply.QueryData.QueryID, matches); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnDirEvents(new DirEventsReplyEventArgs(eventsReply.QueryData.QueryID, matches)); } } - private void EventInfoReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void EventInfoReplyHandler(Packet packet, Simulator simulator) { - if (OnEventInfo != null) + if (m_EventInfoReply != null) { EventInfoReplyPacket eventReply = (EventInfoReplyPacket)packet; EventInfo evinfo = new EventInfo(); @@ -1203,14 +1385,16 @@ namespace OpenMetaverse evinfo.SimName = Utils.BytesToString(eventReply.EventData.SimName); evinfo.GlobalPos = eventReply.EventData.GlobalPos; - try { OnEventInfo(evinfo); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnEventInfo(new EventInfoReplyEventArgs(evinfo)); } } - private void DirPlacesReplyHandler(Packet packet, Simulator simulator) + /// Process an incoming packet + /// The packet containing the data + /// The simulator the packet originated from + protected void DirPlacesReplyHandler(Packet packet, Simulator simulator) { - if (OnDirPlacesReply != null) + if (m_DirPlaces != null) { DirPlacesReplyPacket reply = (DirPlacesReplyPacket)packet; List result = new List(); @@ -1223,16 +1407,169 @@ namespace OpenMetaverse p.Name = Utils.BytesToString(reply.QueryReplies[i].Name); p.Dwell = reply.QueryReplies[i].Dwell; p.Auction = reply.QueryReplies[i].Auction; - p.ForSale = reply.QueryReplies[i].ForSale; + p.ForSale = reply.QueryReplies[i].ForSale; result.Add(p); } - try { OnDirPlacesReply(reply.QueryData[0].QueryID, result); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + OnDirPlaces(new DirPlacesReplyEventArgs(reply.QueryData[0].QueryID, result)); } } #endregion Packet Handlers } + + #region DirectoryManager EventArgs Classes + + /// Contains the Event data returned from the data server from an EventInfoRequest + public class EventInfoReplyEventArgs : EventArgs + { + private readonly DirectoryManager.EventInfo m_MatchedEvent; + + /// + /// A single EventInfo object containing the details of an event + /// + public DirectoryManager.EventInfo MatchedEvent { get { return m_MatchedEvent; } } + + /// Construct a new instance of the EventInfoReplyEventArgs class + /// A single EventInfo object containing the details of an event + public EventInfoReplyEventArgs(DirectoryManager.EventInfo matchedEvent) + { + this.m_MatchedEvent = matchedEvent; + } + } + + /// Contains the "Event" detail data returned from the data server + public class DirEventsReplyEventArgs : EventArgs + { + private readonly UUID m_QueryID; + /// The ID returned by + public UUID QueryID { get { return m_QueryID; } } + + private readonly List m_matchedEvents; + + /// A list of "Events" returned by the data server + public List MatchedEvents { get { return m_matchedEvents; } } + + /// Construct a new instance of the DirEventsReplyEventArgs class + /// The ID of the query returned by the data server. + /// This will correlate to the ID returned by the method + /// A list containing the "Events" returned by the search query + public DirEventsReplyEventArgs(UUID queryID, List matchedEvents) + { + this.m_QueryID = queryID; + this.m_matchedEvents = matchedEvents; + } + } + + /// Contains the "Event" list data returned from the data server + public class PlacesReplyEventArgs : EventArgs + { + private readonly UUID m_QueryID; + /// The ID returned by + public UUID QueryID { get { return m_QueryID; } } + + private readonly List m_MatchedPlaces; + + /// A list of "Places" returned by the data server + public List MatchedPlaces { get { return m_MatchedPlaces; } } + + /// + /// Construct a new instance of PlacesReplyEventArgs class + /// + /// The ID of the query returned by the data server. + /// This will correlate to the ID returned by the method + /// A list containing the "Places" returned by the data server query + public PlacesReplyEventArgs(UUID queryID, List matchedPlaces) + { + this.m_QueryID = queryID; + this.m_MatchedPlaces = matchedPlaces; + } + } + + /// Contains the places data returned from the data server + public class DirPlacesReplyEventArgs : EventArgs + { + private readonly UUID m_QueryID; + /// The ID returned by + public UUID QueryID { get { return m_QueryID; } } + + private readonly List m_MatchedParcels; + + /// A list containing Places data returned by the data server + public List MatchedParcels { get { return m_MatchedParcels; } } + + /// + /// Construct a new instance of the DirPlacesReplyEventArgs class + /// + /// The ID of the query returned by the data server. + /// This will correlate to the ID returned by the method + /// A list containing land sales data returned by the data server + public DirPlacesReplyEventArgs(UUID queryID, List matchedParcels) + { + this.m_QueryID = queryID; + this.m_MatchedParcels = matchedParcels; + } + } + + /// Contains the classified data returned from the data server + public class DirClassifiedsReplyEventArgs : EventArgs + { + private readonly List m_Classifieds; + /// + public List Classifieds { get { return m_Classifieds; } } + + public DirClassifiedsReplyEventArgs(List classifieds) + { + this.m_Classifieds = classifieds; + } + } + + /// Contains the group data returned from the data server + public class DirGroupsReplyEventArgs : EventArgs + { + private readonly UUID m_QueryID; + /// The ID returned by + public UUID QueryID { get { return m_QueryID; } } + + private readonly List m_matchedGroups; + public List MatchedGroups { get { return m_matchedGroups; } } + + public DirGroupsReplyEventArgs(UUID queryID, List matchedGroups) + { + this.m_QueryID = queryID; + this.m_matchedGroups = matchedGroups; + } + } + + /// Contains the people data returned from the data server + public class DirPeopleReplyEventArgs : EventArgs + { + private readonly UUID m_QueryID; + /// The ID returned by + public UUID QueryID { get { return m_QueryID; } } + + private readonly List m_MatchedPeople; + + public List MatchedPeople { get { return m_MatchedPeople; } } + + public DirPeopleReplyEventArgs(UUID queryID, List matchedPeople) + { + this.m_QueryID = queryID; + this.m_MatchedPeople = matchedPeople; + } + } + + /// Contains the land sales data returned from the data server + public class DirLandReplyEventArgs : EventArgs + { + private readonly List m_DirParcels; + public List DirParcels { get { return m_DirParcels; } } + + public DirLandReplyEventArgs(List dirParcels) + { + this.m_DirParcels = dirParcels; + } + } + #endregion } diff --git a/OpenMetaverse/Helpers.cs b/OpenMetaverse/Helpers.cs index c136dee3..83f06373 100644 --- a/OpenMetaverse/Helpers.cs +++ b/OpenMetaverse/Helpers.cs @@ -518,6 +518,38 @@ namespace OpenMetaverse } return prims; - } + } + + /// + /// Converts a struct or class object containing fields only into a key value separated string + /// + /// The struct object + /// A string containing the struct fields as the keys, and the field value as the value separated + /// + /// + /// // Add the following code to any struct or class containing only fields to override the ToString() + /// // method to display the values of the passed object + /// + /// /// Print the struct data as a string + /// ///A string containing the field name, and field value + ///public override string ToString() + ///{ + /// return Helpers.StructToString(this); + ///} + /// + /// + public static string StructToString(object t) + { + StringBuilder result = new StringBuilder(); + Type structType = t.GetType(); + FieldInfo[] fields = structType.GetFields(); + + foreach (FieldInfo field in fields) + { + result.Append(field.Name + ": " + field.GetValue(t) + " "); + } + result.AppendLine(); + return result.ToString().TrimEnd(); + } } } diff --git a/Programs/GridImageUpload/frmGridImageUpload.cs b/Programs/GridImageUpload/frmGridImageUpload.cs index 7579f67c..7c863d27 100644 --- a/Programs/GridImageUpload/frmGridImageUpload.cs +++ b/Programs/GridImageUpload/frmGridImageUpload.cs @@ -293,17 +293,17 @@ namespace GridImageUpload if (sendTo.Length > 0) { AutoResetEvent lookupEvent = new AutoResetEvent(false); - UUID thisQueryID = UUID.Random(); + UUID thisQueryID = UUID.Zero; bool lookupSuccess = false; - DirectoryManager.DirPeopleReplyCallback callback = - delegate(UUID queryID, List matchedPeople) + EventHandler callback = + delegate(object s, DirPeopleReplyEventArgs ep) { - if (queryID == thisQueryID) + if (ep.QueryID == thisQueryID) { - if (matchedPeople.Count > 0) + if (ep.MatchedPeople.Count > 0) { - SendToID = matchedPeople[0].AgentID; + SendToID = ep.MatchedPeople[0].AgentID; lookupSuccess = true; } @@ -311,11 +311,11 @@ namespace GridImageUpload } }; - Client.Directory.OnDirPeopleReply += callback; - Client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, sendTo, 0, thisQueryID); + Client.Directory.DirPeopleReply += callback; + thisQueryID = Client.Directory.StartPeopleSearch(sendTo, 0); bool eventSuccess = lookupEvent.WaitOne(10 * 1000, false); - Client.Directory.OnDirPeopleReply -= callback; + Client.Directory.DirPeopleReply -= callback; if (eventSuccess && lookupSuccess) { diff --git a/Programs/examples/TestClient/ClientManager.cs b/Programs/examples/TestClient/ClientManager.cs index 68095caf..8db0af6b 100644 --- a/Programs/examples/TestClient/ClientManager.cs +++ b/Programs/examples/TestClient/ClientManager.cs @@ -139,26 +139,26 @@ namespace OpenMetaverse.TestClient if (client.MasterKey == UUID.Zero) { - UUID query = UUID.Random(); - DirectoryManager.DirPeopleReplyCallback peopleDirCallback = - delegate(UUID queryID, List matchedPeople) + UUID query = UUID.Zero; + EventHandler peopleDirCallback = + delegate(object sender, DirPeopleReplyEventArgs e) { - if (queryID == query) + if (e.QueryID == query) { - if (matchedPeople.Count != 1) + if (e.MatchedPeople.Count != 1) { Logger.Log("Unable to resolve master key from " + client.MasterName, Helpers.LogLevel.Warning); } else { - client.MasterKey = matchedPeople[0].AgentID; + client.MasterKey = e.MatchedPeople[0].AgentID; Logger.Log("Master key resolved to " + client.MasterKey, Helpers.LogLevel.Info); } } }; - client.Directory.OnDirPeopleReply += peopleDirCallback; - client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, client.MasterName, 0, query); + client.Directory.DirPeopleReply += peopleDirCallback; + query = client.Directory.StartPeopleSearch(client.MasterName, 0); } Logger.Log("Logged in " + client.ToString(), Helpers.LogLevel.Info); diff --git a/Programs/examples/TestClient/Command.cs b/Programs/examples/TestClient/Command.cs index 499be474..be13c2dd 100644 --- a/Programs/examples/TestClient/Command.cs +++ b/Programs/examples/TestClient/Command.cs @@ -20,7 +20,8 @@ namespace OpenMetaverse.TestClient Friends, Groups, Other, - Unknown + Unknown, + Search } public abstract class Command : IComparable diff --git a/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs index fefed31c..4916856a 100644 --- a/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs +++ b/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs @@ -28,23 +28,24 @@ namespace OpenMetaverse.TestClient.Commands waitQuery.Reset(); StringBuilder result = new StringBuilder(); - DirectoryManager.ClassifiedReplyCallback callback = delegate(List classifieds) + + EventHandler callback = delegate(object sender, DirClassifiedsReplyEventArgs e) { result.AppendFormat("Your search string '{0}' returned {1} classified ads" + System.Environment.NewLine, - searchText, classifieds.Count); - foreach (DirectoryManager.Classified ad in classifieds) + searchText, e.Classifieds.Count); + foreach (DirectoryManager.Classified ad in e.Classifieds) { result.AppendLine(ad.ToString()); } // classifieds are sent 16 ads at a time - if (classifieds.Count < 16) + if (e.Classifieds.Count < 16) { waitQuery.Set(); } }; - Client.Directory.OnClassifiedReply += callback; + Client.Directory.DirClassifiedsReply += callback; UUID searchID = Client.Directory.StartClassifiedSearch(searchText, DirectoryManager.ClassifiedCategories.Any, DirectoryManager.ClassifiedQueryFlags.Mature | DirectoryManager.ClassifiedQueryFlags.PG); @@ -53,9 +54,9 @@ namespace OpenMetaverse.TestClient.Commands result.AppendLine("Timeout waiting for simulator to respond to query."); } - Client.Directory.OnClassifiedReply -= callback; + Client.Directory.DirClassifiedsReply -= callback; return result.ToString(); - } + } } } diff --git a/Programs/examples/TestClient/Commands/Directory/SearchEventsCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchEventsCommand.cs index dfd2daa7..08562992 100644 --- a/Programs/examples/TestClient/Commands/Directory/SearchEventsCommand.cs +++ b/Programs/examples/TestClient/Commands/Directory/SearchEventsCommand.cs @@ -18,6 +18,7 @@ namespace OpenMetaverse.TestClient.Commands public override string Execute(string[] args, UUID fromAgentID) { + // process command line arguments if (args.Length < 1) return "Usage: searchevents [search text]"; @@ -25,9 +26,12 @@ namespace OpenMetaverse.TestClient.Commands for (int i = 0; i < args.Length; i++) searchText += args[i] + " "; searchText = searchText.TrimEnd(); - waitQuery.Reset(); - Client.Directory.OnEventsReply += new DirectoryManager.EventReplyCallback(Directory_OnEventsReply); + waitQuery.Reset(); + + Client.Directory.DirEventsReply += Directory_DirEvents; + + // send the request to the directory manager Client.Directory.StartEventsSearch(searchText, 0); string result; if (waitQuery.WaitOne(20000, false) && Client.Network.Connected) @@ -37,25 +41,27 @@ namespace OpenMetaverse.TestClient.Commands else { result = "Timeout waiting for simulator to respond."; - } - Client.Directory.OnEventsReply -= new DirectoryManager.EventReplyCallback(Directory_OnEventsReply); + } + + Client.Directory.DirEventsReply -= Directory_DirEvents; + return result; } - void Directory_OnEventsReply(UUID queryID, List matchedEvents) + void Directory_DirEvents(object sender, DirEventsReplyEventArgs e) { - if (matchedEvents[0].ID == 0 && matchedEvents.Count == 1) + if (e.MatchedEvents[0].ID == 0 && e.MatchedEvents.Count == 1) { Console.WriteLine("No Results matched your search string"); } else { - foreach (DirectoryManager.EventsSearchData ev in matchedEvents) - { + foreach (DirectoryManager.EventsSearchData ev in e.MatchedEvents) + { Console.WriteLine("Event ID: {0} Event Name: {1} Event Date: {2}", ev.ID, ev.Name, ev.Date); } } - resultCount = matchedEvents.Count; + resultCount = e.MatchedEvents.Count; waitQuery.Set(); } } diff --git a/Programs/examples/TestClient/Commands/Directory/SearchGroupsCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchGroupsCommand.cs new file mode 100644 index 00000000..c09fb698 --- /dev/null +++ b/Programs/examples/TestClient/Commands/Directory/SearchGroupsCommand.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenMetaverse.TestClient.Commands +{ + class SearchGroupsCommand : Command + { + System.Threading.AutoResetEvent waitQuery = new System.Threading.AutoResetEvent(false); + int resultCount = 0; + + public SearchGroupsCommand(TestClient testClient) + { + Name = "searchgroups"; + Description = "Searches groups. Usage: searchgroups [search text]"; + Category = CommandCategory.Groups; + } + + public override string Execute(string[] args, UUID fromAgentID) + { + // process command line arguments + if (args.Length < 1) + return "Usage: searchgroups [search text]"; + + string searchText = string.Empty; + for (int i = 0; i < args.Length; i++) + searchText += args[i] + " "; + searchText = searchText.TrimEnd(); + + waitQuery.Reset(); + + Client.Directory.DirGroupsReply += Directory_DirGroups; + + // send the request to the directory manager + Client.Directory.StartGroupSearch(searchText, 0); + + string result; + if (waitQuery.WaitOne(20000, false) && Client.Network.Connected) + { + result = "Your query '" + searchText + "' matched " + resultCount + " Groups. "; + } + else + { + result = "Timeout waiting for simulator to respond."; + } + + Client.Directory.DirGroupsReply -= Directory_DirGroups; + + return result; + } + + void Directory_DirGroups(object sender, DirGroupsReplyEventArgs e) + { + if (e.MatchedGroups.Count > 0) + { + foreach (DirectoryManager.GroupSearchData group in e.MatchedGroups) + { + Console.WriteLine("Group {1} ({0}) has {2} members", group.GroupID, group.GroupName, group.Members); + } + } + else + { + Console.WriteLine("Didn't find any groups that matched your query :("); + } + waitQuery.Set(); + } + } +} diff --git a/Programs/examples/TestClient/Commands/Directory/SearchLandCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchLandCommand.cs new file mode 100644 index 00000000..2bc75545 --- /dev/null +++ b/Programs/examples/TestClient/Commands/Directory/SearchLandCommand.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenMetaverse.TestClient.Commands +{ + /// + /// + /// + public class SearchLandCommand : Command + { + private System.Threading.AutoResetEvent waitQuery = new System.Threading.AutoResetEvent(false); + private StringBuilder result = new StringBuilder(); + + /// + /// Construct a new instance of the SearchLandCommand + /// + /// + public SearchLandCommand(TestClient testClient) + { + Name = "searchland"; + Description = "Searches for land for sale. for usage information type: searchland"; + Category = CommandCategory.Search; + } + + /// + /// Show commandusage + /// + /// A string containing the parameter usage instructions + public string ShowUsage() + { + return "Usage: searchland [type] [max price] [min size]\n" + + "\twhere [type] is one of: mainland, auction, estate, all\n" + + "\tif [max price] or [min size] are 0 that parameter will be ignored\n\n" + + "example: \"searchland mainland 0 512\" // shows the lowest priced mainland that is larger than 512/m2\n\n"; + } + + /// + /// + /// + /// + /// + /// + public override string Execute(string[] args, UUID fromAgentID) + { + // process command line arguments + if (args.Length < 3) + return ShowUsage(); + + string searchType = args[0].Trim().ToLower(); + int maxPrice; + int minSize; + + DirectoryManager.SearchTypeFlags searchTypeFlags = DirectoryManager.SearchTypeFlags.Any; + + if (searchType.StartsWith("au")) + searchTypeFlags = DirectoryManager.SearchTypeFlags.Auction; + else if (searchType.StartsWith("m")) + searchTypeFlags = DirectoryManager.SearchTypeFlags.Mainland; + else if (searchType.StartsWith("e")) + searchTypeFlags = DirectoryManager.SearchTypeFlags.Estate; + else if (searchType.StartsWith("al")) + searchTypeFlags = DirectoryManager.SearchTypeFlags.Any; + else + return ShowUsage(); + + // initialize some default flags we'll use in the search + DirectoryManager.DirFindFlags queryFlags = DirectoryManager.DirFindFlags.SortAsc | DirectoryManager.DirFindFlags.PerMeterSort + | DirectoryManager.DirFindFlags.IncludeAdult | DirectoryManager.DirFindFlags.IncludePG | DirectoryManager.DirFindFlags.IncludeMature; + + // validate the parameters passed + if (int.TryParse(args[1], out maxPrice) && int.TryParse(args[2], out minSize)) + { + // if the [max price] parameter is greater than 0, we'll enable the flag to limit by price + if (maxPrice > 0) + queryFlags |= DirectoryManager.DirFindFlags.LimitByPrice; + + // if the [min size] parameter is greater than 0, we'll enable the flag to limit by area + if (minSize > 0) + queryFlags |= DirectoryManager.DirFindFlags.LimitByArea; + } + else + { + return ShowUsage(); + } + + //waitQuery.Reset(); + + // subscribe to the event that returns the search results + Client.Directory.DirLandReply += Directory_DirLand; + + // send the request to the directory manager + Client.Directory.StartLandSearch(queryFlags, searchTypeFlags, maxPrice, minSize, 0); + + if (!waitQuery.WaitOne(20000, false) && Client.Network.Connected) + { + result.AppendLine("Timeout waiting for simulator to respond."); + } + + // unsubscribe to the event that returns the search results + Client.Directory.DirLandReply -= Directory_DirLand; + + // return the results + return result.ToString(); + } + + /// + /// Process the search reply + /// + /// + /// + private void Directory_DirLand(object sender, DirLandReplyEventArgs e) + { + + foreach (DirectoryManager.DirectoryParcel searchResult in e.DirParcels) + { + // add the results to the StringBuilder object that contains the results + result.AppendLine(searchResult.ToString()); + } + result.AppendFormat("{0} results" + System.Environment.NewLine, e.DirParcels.Count); + // let the calling method know we have data + waitQuery.Set(); + } + } +} diff --git a/Programs/examples/TestClient/Commands/Directory/SearchPeopleCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchPeopleCommand.cs new file mode 100644 index 00000000..712f44aa --- /dev/null +++ b/Programs/examples/TestClient/Commands/Directory/SearchPeopleCommand.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenMetaverse.TestClient.Commands +{ + class SearchPeopleCommand : Command + { + System.Threading.AutoResetEvent waitQuery = new System.Threading.AutoResetEvent(false); + int resultCount = 0; + + public SearchPeopleCommand(TestClient testClient) + { + Name = "searchpeople"; + Description = "Searches for other avatars. Usage: searchpeople [search text]"; + Category = CommandCategory.Friends; + } + + public override string Execute(string[] args, UUID fromAgentID) + { + // process command line arguments + if (args.Length < 1) + return "Usage: searchpeople [search text]"; + + string searchText = string.Empty; + for (int i = 0; i < args.Length; i++) + searchText += args[i] + " "; + searchText = searchText.TrimEnd(); + + waitQuery.Reset(); + + + Client.Directory.DirPeopleReply += Directory_DirPeople; + + // send the request to the directory manager + Client.Directory.StartPeopleSearch(searchText, 0); + + string result; + if (waitQuery.WaitOne(20000, false) && Client.Network.Connected) + { + result = "Your query '" + searchText + "' matched " + resultCount + " People. "; + } + else + { + result = "Timeout waiting for simulator to respond."; + } + + Client.Directory.DirPeopleReply -= Directory_DirPeople; + + return result; + } + + void Directory_DirPeople(object sender, DirPeopleReplyEventArgs e) + { + if (e.MatchedPeople.Count > 0) + { + foreach (DirectoryManager.AgentSearchData agent in e.MatchedPeople) + { + Console.WriteLine("{0} {1} ({2})", agent.FirstName, agent.LastName, agent.AgentID); + } + } + else + { + Console.WriteLine("Didn't find any people that matched your query :("); + } + waitQuery.Set(); + } + } +} diff --git a/Programs/examples/TestClient/Commands/Directory/SearchPlacesCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchPlacesCommand.cs index 368b45d2..84b83858 100644 --- a/Programs/examples/TestClient/Commands/Directory/SearchPlacesCommand.cs +++ b/Programs/examples/TestClient/Commands/Directory/SearchPlacesCommand.cs @@ -28,12 +28,12 @@ namespace OpenMetaverse.TestClient.Commands waitQuery.Reset(); StringBuilder result = new StringBuilder(); - - DirectoryManager.DirPlacesReplyCallback callback = delegate(UUID queryID, List matchedParcels) + + EventHandler callback = delegate(object sender, PlacesReplyEventArgs e) { result.AppendFormat("Your search string '{0}' returned {1} results" + System.Environment.NewLine, - searchText, matchedParcels.Count); - foreach (DirectoryManager.DirectoryParcel place in matchedParcels) + searchText, e.MatchedPlaces.Count); + foreach (DirectoryManager.PlacesSearchData place in e.MatchedPlaces) { result.AppendLine(place.ToString()); } @@ -41,18 +41,17 @@ namespace OpenMetaverse.TestClient.Commands waitQuery.Set(); }; - Client.Directory.OnDirPlacesReply += callback; - - UUID searchID = Client.Directory.StartClassifiedSearch(searchText, DirectoryManager.ClassifiedCategories.Any, DirectoryManager.ClassifiedQueryFlags.Mature | DirectoryManager.ClassifiedQueryFlags.PG); + Client.Directory.PlacesReply += callback; + Client.Directory.StartPlacesSearch(searchText); if (!waitQuery.WaitOne(20000, false) && Client.Network.Connected) { result.AppendLine("Timeout waiting for simulator to respond to query."); } - Client.Directory.OnDirPlacesReply -= callback; + Client.Directory.PlacesReply -= callback; return result.ToString(); - } + } } } diff --git a/Programs/examples/TestClient/Commands/Directory/ShowEventDetailsCommand.cs b/Programs/examples/TestClient/Commands/Directory/ShowEventDetailsCommand.cs index 0fe1db73..47288a80 100644 --- a/Programs/examples/TestClient/Commands/Directory/ShowEventDetailsCommand.cs +++ b/Programs/examples/TestClient/Commands/Directory/ShowEventDetailsCommand.cs @@ -17,14 +17,14 @@ namespace OpenMetaverse.TestClient.Commands { if (args.Length < 1) return "Usage: showevent [eventID] (use searchevents to get ID)"; - - Client.Directory.OnEventInfo += new DirectoryManager.EventInfoCallback(Directory_OnEventInfo); + + Client.Directory.EventInfoReply += Directory_EventDetails; uint eventID; if (UInt32.TryParse(args[0], out eventID)) { Client.Directory.EventInfoRequest(eventID); - return "Query Sent"; + return "Sent query for Event " + eventID; } else { @@ -32,16 +32,19 @@ namespace OpenMetaverse.TestClient.Commands } } - void Directory_OnEventInfo(DirectoryManager.EventInfo matchedEvent) + void Directory_EventDetails(object sender, EventInfoReplyEventArgs e) { - float x,y; - Helpers.GlobalPosToRegionHandle((float)matchedEvent.GlobalPos.X, (float)matchedEvent.GlobalPos.Y, out x, out y); - StringBuilder sb = new StringBuilder(); - sb.AppendFormat(" Name: {0} ({1})" + System.Environment.NewLine, matchedEvent.Name, matchedEvent.ID); - sb.AppendFormat(" Location: {0}/{1}/{2}" + System.Environment.NewLine, matchedEvent.SimName, x, y); - sb.AppendFormat(" Date: {0}" + System.Environment.NewLine, matchedEvent.Date); - sb.AppendFormat("Description: {0}" + System.Environment.NewLine, matchedEvent.Desc); + float x, y; + Helpers.GlobalPosToRegionHandle((float)e.MatchedEvent.GlobalPos.X, (float)e.MatchedEvent.GlobalPos.Y, out x, out y); + StringBuilder sb = new StringBuilder("secondlife://" + e.MatchedEvent.SimName + "/" + x + "/" + y + "/0" + System.Environment.NewLine); + sb.AppendLine(e.MatchedEvent.ToString()); + + //sb.AppendFormat(" Name: {0} ({1})" + System.Environment.NewLine, e.MatchedEvent.Name, e.MatchedEvent.ID); + //sb.AppendFormat(" Location: {0}/{1}/{2}" + System.Environment.NewLine, e.MatchedEvent.SimName, x, y); + //sb.AppendFormat(" Date: {0}" + System.Environment.NewLine, e.MatchedEvent.Date); + //sb.AppendFormat("Description: {0}" + System.Environment.NewLine, e.MatchedEvent.Desc); Console.WriteLine(sb.ToString()); + Client.Directory.EventInfoReply -= Directory_EventDetails; } } } diff --git a/Programs/examples/TestClient/Commands/Groups/JoinGroupCommand.cs b/Programs/examples/TestClient/Commands/Groups/JoinGroupCommand.cs index 8eb0714e..fcbed773 100644 --- a/Programs/examples/TestClient/Commands/Groups/JoinGroupCommand.cs +++ b/Programs/examples/TestClient/Commands/Groups/JoinGroupCommand.cs @@ -45,13 +45,15 @@ namespace OpenMetaverse.TestClient for (int i = 0; i < args.Length; i++) groupName += args[i] + " "; groupName = groupName.Trim(); - DirectoryManager.DirGroupsReplyCallback callback = new DirectoryManager.DirGroupsReplyCallback(Directory_OnDirGroupsReply); - Client.Directory.OnDirGroupsReply += callback; - queryID = Client.Directory.StartGroupSearch(DirectoryManager.DirFindFlags.Groups, groupName, 0); + + Client.Directory.DirGroupsReply += Directory_DirGroups; + + queryID = Client.Directory.StartGroupSearch(groupName, 0); GetGroupsSearchEvent.WaitOne(60000, false); - Client.Directory.OnDirGroupsReply -= callback; + Client.Directory.DirGroupsReply -= Directory_DirGroups; + GetGroupsSearchEvent.Reset(); } @@ -82,6 +84,48 @@ namespace OpenMetaverse.TestClient return "Unable to join the group " + resolvedGroupName; } + void Directory_DirGroups(object sender, DirGroupsReplyEventArgs e) + { + if (queryID == e.QueryID) + { + queryID = UUID.Zero; + if (e.MatchedGroups.Count < 1) + { + Console.WriteLine("ERROR: Got an empty reply"); + } + else + { + if (e.MatchedGroups.Count > 1) + { + /* A.Biondi + * The Group search doesn't work as someone could expect... + * It'll give back to you a long list of groups even if the + * searchText (groupName) matches esactly one of the groups + * names present on the server, so we need to check each result. + * UUIDs of the matching groups are written on the console. + */ + Console.WriteLine("Matching groups are:\n"); + foreach (DirectoryManager.GroupSearchData groupRetrieved in e.MatchedGroups) + { + Console.WriteLine(groupRetrieved.GroupName + "\t\t\t(" + + Name + " UUID " + groupRetrieved.GroupID.ToString() + ")"); + + if (groupRetrieved.GroupName.ToLower() == groupName.ToLower()) + { + resolvedGroupID = groupRetrieved.GroupID; + resolvedGroupName = groupRetrieved.GroupName; + break; + } + } + if (string.IsNullOrEmpty(resolvedGroupName)) + resolvedGroupName = "Ambiguous name. Found " + e.MatchedGroups.Count.ToString() + " groups (UUIDs on console)"; + } + + } + GetGroupsSearchEvent.Set(); + } + } + void Groups_OnGroupJoined(UUID groupID, bool success) { Console.WriteLine(Client.ToString() + (success ? " joined " : " failed to join ") + groupID.ToString()); @@ -102,48 +146,6 @@ namespace OpenMetaverse.TestClient joinedGroup = success; GetGroupsSearchEvent.Set(); - } - - void Directory_OnDirGroupsReply(UUID queryid, List matchedGroups) - { - if (queryID == queryid) - { - queryID = UUID.Zero; - if (matchedGroups.Count < 1) - { - Console.WriteLine("ERROR: Got an empty reply"); - } - else - { - if (matchedGroups.Count > 1) - { - /* A.Biondi - * The Group search doesn't work as someone could expect... - * It'll give back to you a long list of groups even if the - * searchText (groupName) matches esactly one of the groups - * names present on the server, so we need to check each result. - * UUIDs of the matching groups are written on the console. - */ - Console.WriteLine("Matching groups are:\n"); - foreach (DirectoryManager.GroupSearchData groupRetrieved in matchedGroups) - { - Console.WriteLine(groupRetrieved.GroupName + "\t\t\t(" + - Name + " UUID " + groupRetrieved.GroupID.ToString() + ")"); - - if (groupRetrieved.GroupName.ToLower() == groupName.ToLower()) - { - resolvedGroupID = groupRetrieved.GroupID; - resolvedGroupName = groupRetrieved.GroupName; - break; - } - } - if (string.IsNullOrEmpty(resolvedGroupName)) - resolvedGroupName = "Ambiguous name. Found " + matchedGroups.Count.ToString() + " groups (UUIDs on console)"; - } - - } - GetGroupsSearchEvent.Set(); - } - } + } } } diff --git a/Programs/examples/TestClient/Commands/System/SetMasterCommand.cs b/Programs/examples/TestClient/Commands/System/SetMasterCommand.cs index 32f51db6..c5dd0823 100644 --- a/Programs/examples/TestClient/Commands/System/SetMasterCommand.cs +++ b/Programs/examples/TestClient/Commands/System/SetMasterCommand.cs @@ -31,21 +31,21 @@ namespace OpenMetaverse.TestClient if (masterName.Length == 0) return "Usage: setmaster [name]"; - DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler); - Client.Directory.OnDirPeopleReply += callback; + EventHandler callback = KeyResolvHandler; + Client.Directory.DirPeopleReply += callback; - query = Client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, masterName, 0); + query = Client.Directory.StartPeopleSearch(masterName, 0); if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false)) { Client.MasterKey = resolvedMasterKey; keyResolution.Reset(); - Client.Directory.OnDirPeopleReply -= callback; + Client.Directory.DirPeopleReply -= callback; } else { keyResolution.Reset(); - Client.Directory.OnDirPeopleReply -= callback; + Client.Directory.DirPeopleReply -= callback; return "Unable to obtain UUID for \"" + masterName + "\". Master unchanged."; } @@ -56,12 +56,12 @@ namespace OpenMetaverse.TestClient return String.Format("Master set to {0} ({1})", masterName, Client.MasterKey.ToString()); } - private void KeyResolvHandler(UUID queryid, List matches) + private void KeyResolvHandler(object sender, DirPeopleReplyEventArgs e) { - if (query != queryid) + if (query != e.QueryID) return; - resolvedMasterKey = matches[0].AgentID; + resolvedMasterKey = e.MatchedPeople[0].AgentID; keyResolution.Set(); query = UUID.Zero; }