diff --git a/OpenMetaverse/DirectoryManager.cs b/OpenMetaverse/DirectoryManager.cs
index 2c909059..e97d727e 100644
--- a/OpenMetaverse/DirectoryManager.cs
+++ b/OpenMetaverse/DirectoryManager.cs
@@ -34,7 +34,7 @@ using OpenMetaverse.Messages.Linden;
namespace OpenMetaverse
{
///
- /// Access to the Linden dataserver which allows searching for land, events, people, etc
+ /// Access to the dataserver which allows searching for land, events, people, etc
///
public class DirectoryManager
{
@@ -43,11 +43,11 @@ namespace OpenMetaverse
///
public enum ClassifiedCategories
{
- ///
+ /// Classified is listed in the Any category
Any = 0,
- ///
+ /// Classified is shopping related
Shopping,
- ///
+ /// Classified is
LandRental,
///
PropertyRental,
@@ -65,24 +65,37 @@ namespace OpenMetaverse
Personal
}
+ ///
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
}
///
- /// Modifier flags sent to DirectoryManager to select the behaviour of the
+ /// Modifier flags sent to DirectoryManager to change the behavior of the
/// query
///
/// Land Search Flags required in addition to specify land maturity rating:
@@ -202,14 +215,56 @@ namespace OpenMetaverse
public UUID ID;
/// The title of this classified ad
public string Name;
- /// Unknown
- public byte Flags;
+ /// 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;
+
+ ///
+ /// Display a classified ad in a one line human readable format
+ ///
+ /// A string representing a single classified ad
+ 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);
+ }
+ }
+
+ ///
+ /// 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,
}
///
@@ -245,9 +300,10 @@ namespace OpenMetaverse
public string FirstName;
/// Agents last name
public string LastName;
- /// Agents
+ /// Agents
public UUID AgentID;
}
+
///
/// Response to a "Groups" Search
///
@@ -394,7 +450,10 @@ namespace OpenMetaverse
private GridClient Client;
-
+ ///
+ /// Constructs a new instance of the DirectoryManager class
+ ///
+ /// An instance of GridClient
public DirectoryManager(GridClient client)
{
Client = client;
@@ -410,18 +469,58 @@ namespace OpenMetaverse
Client.Network.RegisterCallback(PacketType.DirEventsReply, new NetworkManager.PacketCallback(EventsReplyHandler));
Client.Network.RegisterCallback(PacketType.EventInfoReply, new NetworkManager.PacketCallback(EventInfoReplyHandler));
Client.Network.RegisterCallback(PacketType.DirPlacesReply, new NetworkManager.PacketCallback(DirPlacesReplyHandler));
-
}
- public UUID StartClassifiedSearch(string searchText, ClassifiedCategories categories, bool mature)
+ // 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 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
+ ///
+ /// 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)
+ ///
+ /// 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)categories;
- query.QueryData.QueryFlags = (uint)(mature ? 0 : 2);
+
+ query.QueryData.Category = (uint)category;
+ query.QueryData.QueryFlags = (uint)queryFlags;
query.QueryData.QueryID = queryID;
query.QueryData.QueryText = Utils.StringToBytes(searchText);
@@ -474,7 +573,7 @@ namespace OpenMetaverse
/// each query.
public UUID StartLandSearch(SearchTypeFlags typeFlags)
{
- return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0);
+ return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0);
}
///
@@ -541,6 +640,7 @@ namespace OpenMetaverse
return queryID;
}
+
///
/// Starts a search for a Group in the directory manager
///
@@ -561,6 +661,14 @@ namespace OpenMetaverse
return StartGroupSearch(findFlags, searchText, queryStart, UUID.Random());
}
+ ///
+ /// Search for groups
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public UUID StartGroupSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID)
{
DirFindQueryPacket find = new DirFindQueryPacket();
@@ -574,11 +682,26 @@ namespace OpenMetaverse
return queryID;
}
+ ///
+ /// Search the people directory for other avatars
+ ///
+ ///
+ ///
+ ///
+ ///
public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart)
{
return StartPeopleSearch(findFlags, searchText, queryStart, UUID.Random());
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID)
{
DirFindQueryPacket find = new DirFindQueryPacket();
@@ -595,7 +718,7 @@ namespace OpenMetaverse
}
///
- /// Search "places" for Land you personally own
+ /// Search "places" for parcels of land you personally own
///
public UUID StartPlacesSearch()
{
@@ -764,7 +887,7 @@ namespace OpenMetaverse
classified.CreationDate = Utils.UnixTimeToDateTime(block.CreationDate);
classified.ExpirationDate = Utils.UnixTimeToDateTime(block.ExpirationDate);
- classified.Flags = block.ClassifiedFlags;
+ classified.Flags = (ClassifiedFlags)block.ClassifiedFlags;
classified.ID = block.ClassifiedID;
classified.Name = Utils.BytesToString(block.Name);
classified.Price = block.PriceForListing;
diff --git a/OpenMetaverse/PacketDecoder.cs b/OpenMetaverse/PacketDecoder.cs
index 8cb0ad30..25416e6b 100644
--- a/OpenMetaverse/PacketDecoder.cs
+++ b/OpenMetaverse/PacketDecoder.cs
@@ -115,10 +115,13 @@ namespace OpenMetaverse.Packets
AddCallback("TransferInfo.TargetType", DecodeTransferTargetType);
AddCallback("TransferData.ChannelType", DecodeTransferChannelType);
// Directory Manager
+ AddCallback("DirClassifiedQuery.QueryData.QueryFlags", DecodeDirClassifiedQueryFlags);
AddCallback("QueryData.QueryFlags", DecodeDirQueryFlags);
AddCallback("Category", DecodeCategory);
AddCallback("QueryData.SearchType", SearchTypeFlags);
+ AddCallback("ClassifiedFlags", DecodeDirClassifiedFlags);
+
AddCallback("ParcelAccessListRequest.Data.Flags", DecodeParcelACL);
AddCallback("ParcelAccessListReply.Data.Flags", DecodeParcelACL);
//AddCallback("ParcelAccessListReply.List.Flags", DecodeParcelACLReply);
@@ -845,6 +848,22 @@ namespace OpenMetaverse.Packets
"(" + (DirectoryManager.DirFindFlags)(uint)fieldData + ")");
}
+ private static string DecodeDirClassifiedQueryFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedQueryFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.ClassifiedQueryFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeDirClassifiedFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.ClassifiedFlags)(byte)fieldData + ")");
+ }
+
private static string DecodeParcelACL(string fieldName, object fieldData)
{
return String.Format("{0,30}: {1,-10} {2,-29} [AccessList]",
diff --git a/OpenMetaverse/ParcelManager.cs b/OpenMetaverse/ParcelManager.cs
index f8a0c727..9823548a 100644
--- a/OpenMetaverse/ParcelManager.cs
+++ b/OpenMetaverse/ParcelManager.cs
@@ -117,34 +117,34 @@ namespace OpenMetaverse
}
///
- ///
+ /// The tool to use when modifying terrain levels
///
public enum TerraformAction : byte
{
- ///
+ /// Level the terrain
Level = 0,
- ///
+ /// Raise the terrain
Raise = 1,
- ///
+ /// Lower the terrain
Lower = 2,
- ///
+ /// Smooth the terrain
Smooth = 3,
- ///
+ /// Add random noise to the terrain
Noise = 4,
- ///
+ /// Revert terrain to simulator default
Revert = 5
}
///
- ///
+ /// The tool size to use when changing terrain levels
///
public enum TerraformBrushSize : byte
{
- ///
+ /// Small
Small = 1,
- ///
+ /// Medium
Medium = 2,
- ///
+ /// Large
Large = 4
}
@@ -178,6 +178,7 @@ namespace OpenMetaverse
/// the BorderWest and BorderSouth values are bit flags that get attached
/// to the value stored in the first three bits. Bits four, five, and six
/// are unused
+ [Flags]
public enum ParcelOverlayType : byte
{
/// Public land
diff --git a/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs b/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs
new file mode 100644
index 00000000..fefed31c
--- /dev/null
+++ b/Programs/examples/TestClient/Commands/Directory/SearchClassifiedsCommand.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenMetaverse.TestClient.Commands
+{
+ class SearchClassifiedsCommand : Command
+ {
+ System.Threading.AutoResetEvent waitQuery = new System.Threading.AutoResetEvent(false);
+ int resultCount;
+
+ public SearchClassifiedsCommand(TestClient testClient)
+ {
+ Name = "searchclassifieds";
+ Description = "Searches Classified Ads. Usage: searchclassifieds [search text]";
+ Category = CommandCategory.Other;
+ }
+
+ public override string Execute(string[] args, UUID fromAgentID)
+ {
+ if (args.Length < 1)
+ return "Usage: searchclassifieds [search text]";
+
+ string searchText = string.Empty;
+ for (int i = 0; i < args.Length; i++)
+ searchText += args[i] + " ";
+ searchText = searchText.TrimEnd();
+ waitQuery.Reset();
+
+ StringBuilder result = new StringBuilder();
+ DirectoryManager.ClassifiedReplyCallback callback = delegate(List classifieds)
+ {
+ result.AppendFormat("Your search string '{0}' returned {1} classified ads" + System.Environment.NewLine,
+ searchText, classifieds.Count);
+ foreach (DirectoryManager.Classified ad in classifieds)
+ {
+ result.AppendLine(ad.ToString());
+ }
+
+ // classifieds are sent 16 ads at a time
+ if (classifieds.Count < 16)
+ {
+ waitQuery.Set();
+ }
+ };
+
+ Client.Directory.OnClassifiedReply += callback;
+
+ UUID searchID = Client.Directory.StartClassifiedSearch(searchText, DirectoryManager.ClassifiedCategories.Any, DirectoryManager.ClassifiedQueryFlags.Mature | DirectoryManager.ClassifiedQueryFlags.PG);
+
+ if (!waitQuery.WaitOne(20000, false) && Client.Network.Connected)
+ {
+ result.AppendLine("Timeout waiting for simulator to respond to query.");
+ }
+
+ Client.Directory.OnClassifiedReply -= callback;
+
+ return result.ToString();
+ }
+ }
+}