/*
* Copyright (c) 2006-2014, openmetaverse.org
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.org nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Threading;
using System.Collections.Generic;
using OpenMetaverse.Packets;
using OpenMetaverse.Interfaces;
using OpenMetaverse.Messages.Linden;
namespace OpenMetaverse
{
///
/// Access to the data server which allows searching for land, events, people, etc
///
public class DirectoryManager
{
#region Enums
/// Classified Ad categories
public enum ClassifiedCategories
{
/// Classified is listed in the Any category
Any = 0,
/// Classified is shopping related
Shopping,
/// Classified is
LandRental,
///
PropertyRental,
///
SpecialAttraction,
///
NewProducts,
///
Employment,
///
Wanted,
///
Service,
///
Personal
}
/// Event Categories
public enum EventCategories
{
///
All = 0,
///
Discussion = 18,
///
Sports = 19,
///
LiveMusic = 20,
///
Commercial = 22,
///
Nightlife = 23,
///
Games = 24,
///
Pageants = 25,
///
Education = 26,
///
Arts = 27,
///
Charity = 28,
///
Miscellaneous = 29
}
///
/// 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, not all flags are available in all queries
///
[Flags]
public enum DirFindFlags
{
/// Query the People database
People = 1 << 0,
///
Online = 1 << 1,
//
//[Obsolete]
//Places = 1 << 2,
///
Events = 1 << 3,
/// Query the Groups database
Groups = 1 << 4,
/// Query the Events database
DateEvents = 1 << 5,
/// Query the land holdings database for land owned by the currently connected agent
AgentOwned = 1 << 6,
///
ForSale = 1 << 7,
/// Query the land holdings database for land which is owned by a Group
GroupOwned = 1 << 8,
//
//[Obsolete]
//Auction = 1 << 9,
/// Specifies the query should pre sort the results based upon traffic
/// when searching the Places database
DwellSort = 1 << 10,
///
PgSimsOnly = 1 << 11,
///
PicturesOnly = 1 << 12,
///
PgEventsOnly = 1 << 13,
///
MatureSimsOnly = 1 << 14,
/// Specifies the query should pre sort the results in an ascending order when searching the land sales database.
/// This flag is only used when searching the land sales database
SortAsc = 1 << 15,
/// Specifies the query should pre sort the results using the SalePrice field when searching the land sales database.
/// This flag is only used when searching the land sales database
PricesSort = 1 << 16,
/// Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database.
/// This flag is only used when searching the land sales database
PerMeterSort = 1 << 17,
/// Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database.
/// This flag is only used when searching the land sales database
AreaSort = 1 << 18,
/// Specifies the query should pre sort the results using the Name field when searching the land sales database.
/// This flag is only used when searching the land sales database
NameSort = 1 << 19,
/// When set, only parcels less than the specified Price will be included when searching the land sales database.
/// This flag is only used when searching the land sales database
LimitByPrice = 1 << 20,
/// When set, only parcels greater than the specified Size will be included when searching the land sales database.
/// This flag is only used when searching the land sales database
LimitByArea = 1 << 21,
///
FilterMature = 1 << 22,
///
PGOnly = 1 << 23,
/// Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases
IncludePG = 1 << 24,
/// Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases
IncludeMature = 1 << 25,
/// Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases
IncludeAdult = 1 << 26,
///
AdultOnly = 1 << 27
}
///
/// Land types to search dataserver for
///
[Flags]
public enum SearchTypeFlags
{
/// Search Auction, Mainland and Estate
Any = -1,
/// Land which is currently up for auction
Auction = 1 << 1,
// Land available to new landowners (formerly the FirstLand program)
//[Obsolete]
//Newbie = 1 << 2,
/// Parcels which are on the mainland (Linden owned) continents
Mainland = 1 << 3,
/// Parcels which are on privately owned simulators
Estate = 1 << 4
}
///
/// The content rating of the event
///
public enum EventFlags
{
/// Event is PG
PG = 0,
/// Event is Mature
Mature = 1,
/// Event is Adult
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
///
public struct Classified
{
/// UUID for this ad, useful for looking up detailed
/// information about it
public UUID ID;
/// The title of this classified ad
public string Name;
/// Flags that show certain options applied to the classified
public ClassifiedFlags Flags;
/// Creation date of the ad
public DateTime CreationDate;
/// Expiration date of the ad
public DateTime ExpirationDate;
/// Price that was paid for this ad
public int Price;
/// Print the struct data as a string
/// A string containing the field name, and field value
public override string ToString()
{
return Helpers.StructToString(this);
}
}
///
/// A parcel retrieved from the dataserver such as results from the
/// "For-Sale" listings or "Places" Search
///
public struct DirectoryParcel
{
/// The unique dataserver parcel ID
/// This id is used to obtain additional information from the entry
/// by using the method
public UUID ID;
/// A string containing the name of the parcel
public string Name;
/// The size of the parcel
/// This field is not returned for Places searches
public int ActualArea;
/// The price of the parcel
/// This field is not returned for Places searches
public int SalePrice;
/// If True, this parcel is flagged to be auctioned
public bool Auction;
/// If true, this parcel is currently set for sale
public bool ForSale;
/// Parcel traffic
public float Dwell;
/// 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 Avatar returned from the dataserver
///
public struct AgentSearchData
{
/// Online status of agent
/// This field appears to be obsolete and always returns false
public bool Online;
/// The agents first name
public string FirstName;
/// The agents last name
public string LastName;
/// 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);
}
}
///
/// Response to a "Groups" Search
///
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);
}
}
///
/// 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;
/// 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);
}
}
///
/// 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);
}
}
///
/// 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;
/// 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);
}
}
#endregion Structs
#region Event delegates, Raise Events
/// The event subscribers. null if no subcribers
private EventHandler m_EventInfoReply;
/// 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);
}
/// Thread sync lock object
private readonly object m_EventDetailLock = new object();
/// 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);
}
/// Thread sync lock object
private readonly object m_DirEventsLock = new object();
/// 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;
/// 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);
}
/// Thread sync lock object
private readonly object m_PlacesLock = new object();
/// 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;
/// 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);
}
/// Thread sync lock object
private readonly object m_DirPlacesLock = new object();
/// 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;
/// 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);
}
/// 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
///
/// An instance of GridClient
public DirectoryManager(GridClient client)
{
Client = client;
Client.Network.RegisterCallback(PacketType.DirClassifiedReply, DirClassifiedReplyHandler);
// Deprecated, replies come in over capabilities
Client.Network.RegisterCallback(PacketType.DirLandReply, DirLandReplyHandler);
Client.Network.RegisterEventCallback("DirLandReply", DirLandReplyEventHandler);
Client.Network.RegisterCallback(PacketType.DirPeopleReply, DirPeopleReplyHandler);
Client.Network.RegisterCallback(PacketType.DirGroupsReply, DirGroupsReplyHandler);
// Deprecated as of viewer 1.2.3
Client.Network.RegisterCallback(PacketType.PlacesReply, PlacesReplyHandler);
Client.Network.RegisterEventCallback("PlacesReply", PlacesReplyEventHandler);
Client.Network.RegisterCallback(PacketType.DirEventsReply, EventsReplyHandler);
Client.Network.RegisterCallback(PacketType.EventInfoReply, EventInfoReplyHandler);
Client.Network.RegisterCallback(PacketType.DirPlacesReply, 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)
{
return UUID.Zero;
}
///
/// Query the data server for a list of classified ads containing the specified string.
/// Defaults to searching for classified placed in any category, and includes PG, Adult and Mature
/// results.
///
/// Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming
/// the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received
///
/// The event is raised when a response is received from the simulator
///
/// A string containing a list of keywords to search for
/// A UUID to correlate the results when the event is raised
public UUID StartClassifiedSearch(string searchText)
{
return StartClassifiedSearch(searchText, ClassifiedCategories.Any, ClassifiedQueryFlags.All);
}
///
/// Query the data server for a list of classified ads which contain specified keywords (Overload)
///
/// The event is raised when a response is received from the simulator
///
/// A string containing a list of keywords to search for
/// The category to search
/// A set of flags which can be ORed to modify query options
/// such as classified maturity rating.
/// A UUID to correlate the results when the event is raised
///
/// Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature
///
/// UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature);
///
///
///
/// Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming
/// 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();
query.AgentData.AgentID = Client.Self.AgentID;
query.AgentData.SessionID = Client.Self.SessionID;
query.QueryData.Category = (uint)category;
query.QueryData.QueryFlags = (uint)queryFlags;
query.QueryData.QueryID = queryID;
query.QueryData.QueryText = Utils.StringToBytes(searchText);
Client.Network.SendPacket(query);
return queryID;
}
///
/// Starts search for places (Overloaded)
///
/// The event is raised when a response is received from the simulator
///
/// Search text
/// Each request is limited to 100 places
/// being returned. To get the first 100 result entries of a request use 0,
/// from 100-199 use 1, 200-299 use 2, etc.
/// A UUID to correlate the results when the event is raised
public UUID StartDirPlacesSearch(string searchText, int queryStart)
{
return StartDirPlacesSearch(searchText, DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeMature
| DirFindFlags.IncludeAdult, ParcelCategory.Any, queryStart);
}
///
/// Queries the dataserver for parcels of land which are flagged to be shown in search
///
/// The event is raised when a response is received from the simulator
///
/// A string containing a list of keywords to search for separated by a space character
/// A set of flags which can be ORed to modify query options
/// such as classified maturity rating.
/// The category to search
/// Each request is limited to 100 places
/// being returned. To get the first 100 result entries of a request use 0,
/// from 100-199 use 1, 200-299 use 2, etc.
/// A UUID to correlate the results when the event is raised
///
/// Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult
///
/// UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0);
///
///
///
/// 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;
query.QueryData.Category = (sbyte)category;
query.QueryData.QueryFlags = (uint)queryFlags;
query.QueryData.QueryID = queryID;
query.QueryData.QueryText = Utils.StringToBytes(searchText);
query.QueryData.QueryStart = queryStart;
query.QueryData.SimName = Utils.StringToBytes(string.Empty);
Client.Network.SendPacket(query);
return queryID;
}
///
/// Starts a search for land sales using the directory
///
/// 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
/// 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 void StartLandSearch(SearchTypeFlags typeFlags)
{
StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0);
}
///
/// Starts a search for land sales using the directory
///
/// 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
/// Maximum price to search for
/// 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.
/// 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 void StartLandSearch(SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart)
{
StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByPrice |
DirFindFlags.LimitByArea, typeFlags, priceLimit, areaLimit, queryStart);
}
///
/// Send a request to the data server for land sales listings
///
///
/// Flags sent to specify query options
///
/// Available flags:
/// Specify the parcel rating with one or more of the following:
/// IncludePG IncludeMature IncludeAdult
///
/// Specify the field to pre sort the results with ONLY ONE of the following:
/// PerMeterSort NameSort AreaSort PricesSort
///
/// Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order
/// SortAsc
///
/// Specify additional filters to limit the results with one or both of the following:
/// LimitByPrice LimitByArea
///
/// Flags can be combined by separating them with the | (pipe) character
///
/// Additional details can be found in
///
/// What type of land to search for. Auction,
/// Estate or Mainland
/// Maximum price to search for when the
/// DirFindFlags.LimitByPrice flag is specified in findFlags
/// Maximum area to search for when the
/// DirFindFlags.LimitByArea flag is specified in findFlags
/// 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.
/// 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
/// fired other than you won't get more than 100 total parcels from
/// each reply.
///
/// Any land set for sale to either anybody or specific to the connected agent will be included in the
/// results if the land is included in the query
///
///
/// // 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 void StartLandSearch(DirFindFlags findFlags, SearchTypeFlags typeFlags, int priceLimit,
int areaLimit, int queryStart)
{
DirLandQueryPacket query = new DirLandQueryPacket();
query.AgentData.AgentID = Client.Self.AgentID;
query.AgentData.SessionID = Client.Self.SessionID;
query.QueryData.Area = areaLimit;
query.QueryData.Price = priceLimit;
query.QueryData.QueryStart = queryStart;
query.QueryData.SearchType = (uint)typeFlags;
query.QueryData.QueryFlags = (uint)findFlags;
query.QueryData.QueryID = UUID.Random();
Client.Network.SendPacket(query);
}
///
/// Search for Groups
///
/// The name or portion of the name of the group you wish to search for
/// Start from the match number
///
public UUID StartGroupSearch(string searchText, int queryStart)
{
return StartGroupSearch(searchText, queryStart, DirFindFlags.Groups | DirFindFlags.IncludePG
| DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult);
}
///
/// Search for Groups
///
/// The name or portion of the name of the group you wish to search for
/// Start from the match number
/// Search flags
///
public UUID StartGroupSearch(string searchText, int queryStart, DirFindFlags flags)
{
DirFindQueryPacket find = new DirFindQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.QueryData.QueryFlags = (uint)flags;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryID = UUID.Random();
find.QueryData.QueryStart = queryStart;
Client.Network.SendPacket(find);
return find.QueryData.QueryID;
}
///
/// Search the People directory for other avatars
///
/// The name or portion of the name of the avatar you wish to search for
///
///
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)DirFindFlags.People;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryID = UUID.Random();
find.QueryData.QueryStart = queryStart;
Client.Network.SendPacket(find);
return find.QueryData.QueryID;
}
///
/// 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.Random());
}
///
/// Searches Places for land owned by the specified group
///
/// 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(UUID groupID)
{
return StartPlacesSearch(DirFindFlags.GroupOwned, ParcelCategory.Any, String.Empty, String.Empty,
groupID, UUID.Random());
}
///
/// Search the Places directory for parcels that are listed in search and contain the specified keywords
///
/// A string containing the keywords to search for
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(string searchText)
{
return StartPlacesSearch(DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult,
ParcelCategory.Any, searchText, String.Empty, UUID.Zero, UUID.Random());
}
///
/// Search Places - All Options
///
/// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc.
/// One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer
/// A string containing a list of keywords to search for separated by a space character
/// String Simulator Name to search in
/// 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)
{
PlacesQueryPacket find = new PlacesQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.AgentData.QueryID = groupID;
find.TransactionData.TransactionID = transactionID;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryFlags = (uint)findFlags;
find.QueryData.Category = (sbyte)searchCategory;
find.QueryData.SimName = Utils.StringToBytes(simulatorName);
Client.Network.SendPacket(find);
return transactionID;
}
///
/// Search All Events with specifid searchText in all categories, includes PG, Mature and Adult
///
/// A string containing a list of keywords to search for separated by a space character
/// Each request is limited to 100 entries
/// being returned. To get the first group of entries of a request use 0,
/// from 100-199 use 100, 200-299 use 200, etc.
/// 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);
}
///
/// Search Events
///
/// A string containing a list of keywords to search for separated by a space character
/// One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult
/// from the Enum
///
/// Multiple flags can be combined by separating the flags with the | (pipe) character
/// "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled
/// For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc.
/// Each request is limited to 100 entries
/// being returned. To get the first group of entries of a request use 0,
/// from 100-199 use 100, 200-299 use 200, etc.
/// EventCategory event is listed under.
/// UUID of query to correlate results in callback.
public UUID StartEventsSearch(string searchText, DirFindFlags queryFlags, string eventDay, uint queryStart, EventCategories category)
{
DirFindQueryPacket find = new DirFindQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
UUID queryID = UUID.Random();
find.QueryData.QueryID = queryID;
find.QueryData.QueryText = Utils.StringToBytes(eventDay + "|" + (int)category + "|" + searchText);
find.QueryData.QueryFlags = (uint)queryFlags;
find.QueryData.QueryStart = (int)queryStart;
Client.Network.SendPacket(find);
return queryID;
}
/// Requests Event Details
/// ID of Event returned from the method
public void EventInfoRequest(uint eventID)
{
EventInfoRequestPacket find = new EventInfoRequestPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.EventData.EventID = eventID;
Client.Network.SendPacket(find);
}
#endregion
#region Blocking Functions
[Obsolete("Use the async StartPeoplSearch method instead")]
public bool PeopleSearch(DirFindFlags findFlags, string searchText, int queryStart,
int timeoutMS, out List results)
{
AutoResetEvent searchEvent = new AutoResetEvent(false);
UUID id = UUID.Zero;
List people = null;
EventHandler callback =
delegate(object sender, DirPeopleReplyEventArgs e)
{
if (id == e.QueryID)
{
people = e.MatchedPeople;
searchEvent.Set();
}
};
DirPeopleReply += callback;
id = StartPeopleSearch(searchText, queryStart);
searchEvent.WaitOne(timeoutMS, false);
DirPeopleReply -= callback;
results = people;
return (results != null);
}
#endregion Blocking Functions
#region Packet Handlers
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void DirClassifiedReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirClassifieds != null)
{
DirClassifiedReplyPacket reply = (DirClassifiedReplyPacket)e.Packet;
List classifieds = new List();
foreach (DirClassifiedReplyPacket.QueryRepliesBlock block in reply.QueryReplies)
{
Classified classified = new Classified();
classified.CreationDate = Utils.UnixTimeToDateTime(block.CreationDate);
classified.ExpirationDate = Utils.UnixTimeToDateTime(block.ExpirationDate);
classified.Flags = (ClassifiedFlags)block.ClassifiedFlags;
classified.ID = block.ClassifiedID;
classified.Name = Utils.BytesToString(block.Name);
classified.Price = block.PriceForListing;
classifieds.Add(classified);
}
OnDirClassifieds(new DirClassifiedsReplyEventArgs(classifieds));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void DirLandReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirLandReply != null)
{
List parcelsForSale = new List();
DirLandReplyPacket reply = (DirLandReplyPacket)e.Packet;
foreach (DirLandReplyPacket.QueryRepliesBlock block in reply.QueryReplies)
{
DirectoryParcel dirParcel = new DirectoryParcel();
dirParcel.ActualArea = block.ActualArea;
dirParcel.ID = block.ParcelID;
dirParcel.Name = Utils.BytesToString(block.Name);
dirParcel.SalePrice = block.SalePrice;
dirParcel.Auction = block.Auction;
dirParcel.ForSale = block.ForSale;
parcelsForSale.Add(dirParcel);
}
OnDirLand(new DirLandReplyEventArgs(parcelsForSale));
}
}
/// 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 (m_DirLandReply != null)
{
List parcelsForSale = new List();
DirLandReplyMessage reply = (DirLandReplyMessage)message;
foreach (DirLandReplyMessage.QueryReply block in reply.QueryReplies)
{
DirectoryParcel dirParcel = new DirectoryParcel();
dirParcel.ActualArea = block.ActualArea;
dirParcel.ID = block.ParcelID;
dirParcel.Name = block.Name;
dirParcel.SalePrice = block.SalePrice;
dirParcel.Auction = block.Auction;
dirParcel.ForSale = block.ForSale;
parcelsForSale.Add(dirParcel);
}
OnDirLand(new DirLandReplyEventArgs(parcelsForSale));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void DirPeopleReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirPeople != null)
{
DirPeopleReplyPacket peopleReply = e.Packet as DirPeopleReplyPacket;
List matches = new List(peopleReply.QueryReplies.Length);
foreach (DirPeopleReplyPacket.QueryRepliesBlock reply in peopleReply.QueryReplies)
{
AgentSearchData searchData = new AgentSearchData();
searchData.Online = reply.Online;
searchData.FirstName = Utils.BytesToString(reply.FirstName);
searchData.LastName = Utils.BytesToString(reply.LastName);
searchData.AgentID = reply.AgentID;
matches.Add(searchData);
}
OnDirPeople(new DirPeopleReplyEventArgs(peopleReply.QueryData.QueryID, matches));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void DirGroupsReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirGroups != null)
{
Packet packet = e.Packet;
DirGroupsReplyPacket groupsReply = (DirGroupsReplyPacket)packet;
List matches = new List(groupsReply.QueryReplies.Length);
foreach (DirGroupsReplyPacket.QueryRepliesBlock reply in groupsReply.QueryReplies)
{
GroupSearchData groupsData = new GroupSearchData();
groupsData.GroupID = reply.GroupID;
groupsData.GroupName = Utils.BytesToString(reply.GroupName);
groupsData.Members = reply.Members;
matches.Add(groupsData);
}
OnDirGroups(new DirGroupsReplyEventArgs(groupsReply.QueryData.QueryID, matches));
}
}
/// 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 (m_Places != null)
{
PlacesReplyMessage replyMessage = (PlacesReplyMessage)message;
List places = new List();
for (int i = 0; i < replyMessage.QueryDataBlocks.Length; i++)
{
PlacesSearchData place = new PlacesSearchData();
place.ActualArea = replyMessage.QueryDataBlocks[i].ActualArea;
place.BillableArea = replyMessage.QueryDataBlocks[i].BillableArea;
place.Desc = replyMessage.QueryDataBlocks[i].Description;
place.Dwell = replyMessage.QueryDataBlocks[i].Dwell;
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;
place.Name = replyMessage.QueryDataBlocks[i].Name;
place.OwnerID = replyMessage.QueryDataBlocks[i].OwnerID;
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);
}
OnPlaces(new PlacesReplyEventArgs(replyMessage.QueryID, places));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void PlacesReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_Places != null)
{
Packet packet = e.Packet;
PlacesReplyPacket placesReply = packet as PlacesReplyPacket;
List places = new List();
foreach (PlacesReplyPacket.QueryDataBlock block in placesReply.QueryData)
{
PlacesSearchData place = new PlacesSearchData();
place.OwnerID = block.OwnerID;
place.Name = Utils.BytesToString(block.Name);
place.Desc = Utils.BytesToString(block.Desc);
place.ActualArea = block.ActualArea;
place.BillableArea = block.BillableArea;
place.Flags = (PlacesFlags)block.Flags;
place.GlobalX = block.GlobalX;
place.GlobalY = block.GlobalY;
place.GlobalZ = block.GlobalZ;
place.SimName = Utils.BytesToString(block.SimName);
place.SnapshotID = block.SnapshotID;
place.Dwell = block.Dwell;
place.Price = block.Price;
places.Add(place);
}
OnPlaces(new PlacesReplyEventArgs(placesReply.TransactionData.TransactionID, places));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void EventsReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirEvents != null)
{
Packet packet = e.Packet;
DirEventsReplyPacket eventsReply = (DirEventsReplyPacket)packet;
List matches = new List(eventsReply.QueryReplies.Length);
foreach (DirEventsReplyPacket.QueryRepliesBlock reply in eventsReply.QueryReplies)
{
EventsSearchData eventsData = new EventsSearchData();
eventsData.Owner = reply.OwnerID;
eventsData.Name = Utils.BytesToString(reply.Name);
eventsData.ID = reply.EventID;
eventsData.Date = Utils.BytesToString(reply.Date);
eventsData.Time = reply.UnixTime;
eventsData.Flags = (EventFlags)reply.EventFlags;
matches.Add(eventsData);
}
OnDirEvents(new DirEventsReplyEventArgs(eventsReply.QueryData.QueryID, matches));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void EventInfoReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_EventInfoReply != null)
{
Packet packet = e.Packet;
EventInfoReplyPacket eventReply = (EventInfoReplyPacket)packet;
EventInfo evinfo = new EventInfo();
evinfo.ID = eventReply.EventData.EventID;
evinfo.Name = Utils.BytesToString(eventReply.EventData.Name);
evinfo.Desc = Utils.BytesToString(eventReply.EventData.Desc);
evinfo.Amount = eventReply.EventData.Amount;
evinfo.Category = (EventCategories)Utils.BytesToUInt(eventReply.EventData.Category);
evinfo.Cover = eventReply.EventData.Cover;
evinfo.Creator = (UUID)Utils.BytesToString(eventReply.EventData.Creator);
evinfo.Date = Utils.BytesToString(eventReply.EventData.Date);
evinfo.DateUTC = eventReply.EventData.DateUTC;
evinfo.Duration = eventReply.EventData.Duration;
evinfo.Flags = (EventFlags)eventReply.EventData.EventFlags;
evinfo.SimName = Utils.BytesToString(eventReply.EventData.SimName);
evinfo.GlobalPos = eventReply.EventData.GlobalPos;
OnEventInfo(new EventInfoReplyEventArgs(evinfo));
}
}
/// Process an incoming packet and raise the appropriate events
/// The sender
/// The EventArgs object containing the packet data
protected void DirPlacesReplyHandler(object sender, PacketReceivedEventArgs e)
{
if (m_DirPlaces != null)
{
Packet packet = e.Packet;
DirPlacesReplyPacket reply = (DirPlacesReplyPacket)packet;
List result = new List();
for (int i = 0; i < reply.QueryReplies.Length; i++)
{
DirectoryParcel p = new DirectoryParcel();
p.ID = reply.QueryReplies[i].ParcelID;
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;
result.Add(p);
}
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 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;
/// A list containing Classified Ads returned by the data server
public List Classifieds { get { return m_Classifieds; } }
/// Construct a new instance of the DirClassifiedsReplyEventArgs class
/// A list of classified ad data returned from the data server
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;
/// A list containing Groups data returned by the data server
public List MatchedGroups { get { return m_matchedGroups; } }
/// Construct a new instance of the DirGroupsReplyEventArgs class
/// The ID of the query returned by the data server.
/// This will correlate to the ID returned by the method
/// A list of groups data returned by the data server
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;
/// A list containing People data returned by the data server
public List MatchedPeople { get { return m_MatchedPeople; } }
/// Construct a new instance of the DirPeopleReplyEventArgs class
/// The ID of the query returned by the data server.
/// This will correlate to the ID returned by the method
/// A list of people data returned by the data server
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;
/// A list containing land forsale data returned by the data server
public List DirParcels { get { return m_DirParcels; } }
/// Construct a new instance of the DirLandReplyEventArgs class
/// A list of parcels for sale returned by the data server
public DirLandReplyEventArgs(List dirParcels)
{
this.m_DirParcels = dirParcels;
}
}
#endregion
}