diff --git a/libsecondlife/DirectoryManager.cs b/libsecondlife/DirectoryManager.cs index d7d9cf0d..f053d924 100644 --- a/libsecondlife/DirectoryManager.cs +++ b/libsecondlife/DirectoryManager.cs @@ -178,6 +178,13 @@ namespace libsecondlife public bool ReservedNewbie; } + public struct AgentSearchData { + public bool Online; + public string FirstName; + public string LastName; + public LLUUID AgentID; + } + /*/// public LLUUID OwnerID; /// @@ -207,6 +214,11 @@ namespace libsecondlife /// public delegate void DirLandReplyCallback(List dirParcels); + /// + /// + /// + /// + public delegate void DirPeopleReplyCallback(LLUUID queryID, List matchedPeople); /// /// @@ -217,6 +229,7 @@ namespace libsecondlife /// public event DirLandReplyCallback OnDirLandReply; + public event DirPeopleReplyCallback OnDirPeopleReply; private SecondLife Client; @@ -227,6 +240,8 @@ namespace libsecondlife Client.Network.RegisterCallback(PacketType.DirClassifiedReply, new NetworkManager.PacketCallback(DirClassifiedReplyHandler)); Client.Network.RegisterCallback(PacketType.DirLandReply, new NetworkManager.PacketCallback(DirLandReplyHandler)); + Client.Network.RegisterCallback(PacketType.DirPeopleReply, new NetworkManager.PacketCallback(DirPeopleReplyHandler)); + } public LLUUID StartClassifiedSearch(string searchText, ClassifiedCategories categories, bool mature) @@ -328,6 +343,20 @@ namespace libsecondlife return queryID; } + public LLUUID StartPeopleSearch(DirFindFlags findFlags, String searchText) + { + LLUUID queryID = LLUUID.Random(); + DirFindQueryPacket find = new DirFindQueryPacket(); + find.AgentData.AgentID = Client.Network.AgentID; + find.AgentData.SessionID = Client.Network.SessionID; + find.QueryData.QueryFlags = (uint)findFlags; + find.QueryData.QueryText = Helpers.StringToField(searchText); + find.QueryData.QueryID = queryID; + find.QueryData.QueryStart = 0; + Client.Network.SendPacket(find); + return queryID; + } + private void DirClassifiedReplyHandler(Packet packet, Simulator simulator) { if (OnClassifiedReply != null) @@ -380,5 +409,24 @@ namespace libsecondlife catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } } + + protected void DirPeopleReplyHandler(Packet packet, Simulator simulator) + { + if (OnDirPeopleReply != null) + { + DirPeopleReplyPacket peopleReply = 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 = Helpers.FieldToUTF8String(reply.FirstName); + searchData.LastName = Helpers.FieldToUTF8String(reply.LastName); + searchData.AgentID = reply.AgentID; + matches.Add(searchData); + } + try { OnDirPeopleReply(peopleReply.QueryData.QueryID, matches); } + catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } + } + } } } diff --git a/libsecondlife/ObjectManager.cs b/libsecondlife/ObjectManager.cs index 8ac38b19..b9c6d038 100644 --- a/libsecondlife/ObjectManager.cs +++ b/libsecondlife/ObjectManager.cs @@ -503,6 +503,7 @@ namespace libsecondlife Client.Network.RegisterCallback(PacketType.ObjectUpdateCached, new NetworkManager.PacketCallback(CachedUpdateHandler)); Client.Network.RegisterCallback(PacketType.KillObject, new NetworkManager.PacketCallback(KillObjectHandler)); Client.Network.RegisterCallback(PacketType.ObjectPropertiesFamily, new NetworkManager.PacketCallback(ObjectPropertiesFamilyHandler)); + Client.Network.RegisterCallback(PacketType.ObjectProperties, new NetworkManager.PacketCallback(ObjectPropertiesHandler)); // If the callbacks aren't registered there's not point in doing client-side path prediction, // so we set it up here diff --git a/libsecondlife/examples/TestClient/ClientManager.cs b/libsecondlife/examples/TestClient/ClientManager.cs index be27372d..011b89c4 100644 --- a/libsecondlife/examples/TestClient/ClientManager.cs +++ b/libsecondlife/examples/TestClient/ClientManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Xml; +using System.Threading; using libsecondlife; using libsecondlife.Packets; using libsecondlife.AssetSystem; @@ -13,24 +14,25 @@ namespace libsecondlife.TestClient public string FirstName; public string LastName; public string Password; - public string Master; + public string MasterName; + public LLUUID MasterKey; + } + + public class StartPosition + { + public string sim; + public int x; + public int y; + public int z; + + public StartPosition() + { + this.sim = null; + this.x = 0; + this.y = 0; + this.z = 0; + } } - - public class StartPosition - { - public string sim; - public int x; - public int y; - public int z; - - public StartPosition() - { - this.sim = null; - this.x = 0; - this.y = 0; - this.z = 0; - } - } public class ClientManager { @@ -38,9 +40,11 @@ namespace libsecondlife.TestClient public Dictionary> SimPrims = new Dictionary>(); public bool Running = true; - - string contactPerson = String.Empty; - StartPosition startpos = new StartPosition(); + + string contactPerson = String.Empty; + StartPosition startpos = new StartPosition(); + private LLUUID resolvedMasterKey = LLUUID.Zero; + private ManualResetEvent keyResolution = new ManualResetEvent(false); /// /// @@ -48,23 +52,23 @@ namespace libsecondlife.TestClient /// public ClientManager(List accounts, string c) { - this.contactPerson = c; + this.contactPerson = c; foreach (LoginDetails account in accounts) Login(account); } - public ClientManager(List accounts, string c, string s) - { - this.contactPerson = c; - char sep = '/'; - string[] startbits = s.Split(sep); - this.startpos.sim = startbits[0]; - this.startpos.x = int.Parse(startbits[1]); - this.startpos.y = int.Parse(startbits[2]); - this.startpos.z = int.Parse(startbits[3]); - foreach (LoginDetails account in accounts) + public ClientManager(List accounts, string c, string s) + { + this.contactPerson = c; + char sep = '/'; + string[] startbits = s.Split(sep); + this.startpos.sim = startbits[0]; + this.startpos.x = int.Parse(startbits[1]); + this.startpos.y = int.Parse(startbits[2]); + this.startpos.z = int.Parse(startbits[3]); + foreach (LoginDetails account in accounts) Login(account); - } + } /// /// /// @@ -77,12 +81,12 @@ namespace libsecondlife.TestClient { if (c.Self.FirstName == account.FirstName && c.Self.LastName == account.LastName) { - Logout(c); + Logout(c); break; } } - TestClient client = new TestClient(this); + TestClient client = new TestClient(this); // Optimize the throttle client.Throttle.Wind = 0; @@ -91,23 +95,24 @@ namespace libsecondlife.TestClient client.Throttle.Task = 1000000; client.SimPrims = SimPrims; - client.Master = account.Master; + client.MasterName = account.MasterName; + client.MasterKey = account.MasterKey; if (!String.IsNullOrEmpty(this.startpos.sim)) { - if (this.startpos.x == 0 || this.startpos.y == 0 || this.startpos.z == 0) + if (this.startpos.x == 0 || this.startpos.y == 0 || this.startpos.z == 0) { - this.startpos.x = 128; - this.startpos.y = 128; - this.startpos.z = 1; - } + this.startpos.x = 128; + this.startpos.y = 128; + this.startpos.z = 1; + } - string startLoc = NetworkManager.StartLocation(this.startpos.sim, this.startpos.x, this.startpos.y, + string startLoc = NetworkManager.StartLocation(this.startpos.sim, this.startpos.x, this.startpos.y, this.startpos.z); - Console.WriteLine(startLoc); - client.Network.Login(account.FirstName, account.LastName, account.Password, "TestClient", startLoc, + Console.WriteLine(startLoc); + client.Network.Login(account.FirstName, account.LastName, account.Password, "TestClient", startLoc, contactPerson); - } + } else { if (!client.Network.Login(account.FirstName, account.LastName, account.Password, "TestClient", @@ -116,10 +121,32 @@ namespace libsecondlife.TestClient Console.WriteLine("Failed to login " + account.FirstName + " " + account.LastName + ": " + client.Network.LoginMessage); } - } + } if (client.Network.Connected) { + if (account.MasterKey == LLUUID.Zero && !String.IsNullOrEmpty(account.MasterName)) + { + Console.WriteLine("Resolving {0}'s UUID", account.MasterName); + // Find master's key from name + DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler); + client.Directory.OnDirPeopleReply += callback; + client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, account.MasterName); + if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false)) + { + account.MasterKey = resolvedMasterKey; + Console.WriteLine("\"{0}\" resolved to {1}", account.MasterName, account.MasterKey); + } + else + { + Console.WriteLine("Unable to obtain UUID for \"{0}\". No master will be used. Try specifying a key with --masterkey.", account.MasterName); + } + client.Directory.OnDirPeopleReply -= callback; + keyResolution.Reset(); + } + + client.MasterKey = account.MasterKey; + Clients[client.Network.AgentID] = client; Console.WriteLine("Logged in " + client.ToString()); @@ -128,20 +155,52 @@ namespace libsecondlife.TestClient return client; } - /// - /// - /// - /// - /// - public TestClient Login(string[] args) - { + private void KeyResolvHandler(LLUUID queryid, List matches) + { + LLUUID master = matches[0].AgentID; + if (matches.Count > 1) + { + Console.WriteLine("Possible masters:"); + for (int i = 0; i < matches.Count; ++i) + { + Console.WriteLine("{0}: {1}", i, matches[i].FirstName + " " + matches[i].LastName); + } + Console.Write("Ambiguous master, choose one:"); + string read = Console.ReadLine(); + while (read != null) + { + int choice = 0; + if (int.TryParse(read, out choice)) + { + master = matches[choice].AgentID; + break; + } + else + { + Console.WriteLine("Responce misunderstood."); + Console.Write("Type the corresponding number:"); + } + read = Console.ReadLine(); + } + } + resolvedMasterKey = master; + keyResolution.Set(); + } + + /// + /// + /// + /// + /// + public TestClient Login(string[] args) + { LoginDetails account = new LoginDetails(); account.FirstName = args[0]; account.LastName = args[1]; account.Password = args[2]; - - return Login(account); - } + + return Login(account); + } /// /// @@ -164,8 +223,8 @@ namespace libsecondlife.TestClient } } - private void PrintPrompt() - { + private void PrintPrompt() + { int online = 0; foreach (SecondLife client in Clients.Values) @@ -174,14 +233,14 @@ namespace libsecondlife.TestClient } Console.Write(online + " avatars online> "); - } + } - /// - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// + /// public void DoCommandAll(string cmd, LLUUID fromAgentID, LLUUID imSessionID) { string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' }); @@ -200,49 +259,49 @@ namespace libsecondlife.TestClient } else if (firstToken == "quit") { - Quit(); - Console.WriteLine("All clients logged out and program finished running."); + Quit(); + Console.WriteLine("All clients logged out and program finished running."); } else { - // make a copy of the clients list so that it can be iterated without fear of being changed during iteration - Dictionary clientsCopy = new Dictionary(Clients); + // make a copy of the clients list so that it can be iterated without fear of being changed during iteration + Dictionary clientsCopy = new Dictionary(Clients); - foreach (TestClient client in clientsCopy.Values) - client.DoCommand(cmd, fromAgentID, imSessionID); - } + foreach (TestClient client in clientsCopy.Values) + client.DoCommand(cmd, fromAgentID, imSessionID); + } } - /// - /// - /// - /// - public void Logout(TestClient client) - { + /// + /// + /// + /// + public void Logout(TestClient client) + { Clients.Remove(client.Network.AgentID); client.Network.Logout(); - } + } - /// - /// - /// - public void LogoutAll() - { - // make a copy of the clients list so that it can be iterated without fear of being changed during iteration - Dictionary clientsCopy = new Dictionary(Clients); + /// + /// + /// + public void LogoutAll() + { + // make a copy of the clients list so that it can be iterated without fear of being changed during iteration + Dictionary clientsCopy = new Dictionary(Clients); - foreach (TestClient client in clientsCopy.Values) - Logout(client); - } + foreach (TestClient client in clientsCopy.Values) + Logout(client); + } - /// - /// - /// - public void Quit() - { - LogoutAll(); - Running = false; - // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit. - } - } + /// + /// + /// + public void Quit() + { + LogoutAll(); + Running = false; + // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit. + } + } } diff --git a/libsecondlife/examples/TestClient/Commands/Communication/EchoMasterCommand.cs b/libsecondlife/examples/TestClient/Commands/Communication/EchoMasterCommand.cs index ad7c699c..a7c3d3f2 100644 --- a/libsecondlife/examples/TestClient/Commands/Communication/EchoMasterCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Communication/EchoMasterCommand.cs @@ -33,7 +33,7 @@ namespace libsecondlife.TestClient void Self_OnChat(string message, MainAvatar.ChatAudibleLevel audible, MainAvatar.ChatType type, MainAvatar.ChatSourceType sourcetype, string fromName, LLUUID id, LLUUID ownerid, LLVector3 position) { - if (message.Length > 0 && Client.Master == fromName) + if (message.Length > 0 && Client.MasterKey == id) { Client.Self.Chat(message, 0, MainAvatar.ChatType.Normal); } diff --git a/libsecondlife/examples/TestClient/Commands/ExportCommand.cs b/libsecondlife/examples/TestClient/Commands/ExportCommand.cs index 95b13423..2e61d56a 100644 --- a/libsecondlife/examples/TestClient/Commands/ExportCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/ExportCommand.cs @@ -107,6 +107,7 @@ namespace libsecondlife.TestClient } } } + bool complete = RequestObjectProperties(prims, 250); //Serialize it! @@ -160,7 +161,7 @@ namespace libsecondlife.TestClient Client.Objects.SelectObjects(Client.Network.CurrentSim, localids); - return AllPropertiesReceived.WaitOne(3000 + msPerRequest * objects.Count, false); + return AllPropertiesReceived.WaitOne(2000 + msPerRequest * objects.Count, false); } void Objects_OnObjectPropertiesFamily(Simulator simulator, LLObject.ObjectPropertiesFamily properties) diff --git a/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs b/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs index 846d1167..f5074a34 100644 --- a/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Movement/FollowCommand.cs @@ -21,9 +21,6 @@ namespace libsecondlife.TestClient target = target + args[ct] + " "; target = target.TrimEnd(); - if (target.Length == 0) - target = Client.Master; - if (target.Length > 0) { if (Follow(target)) @@ -33,7 +30,10 @@ namespace libsecondlife.TestClient } else { - return "No target specified and no master is set. usage: follow [FirstName LastName])"; + if (Follow(Client.MasterKey)) + return "Following " + Client.MasterKey; + else + return "No target specified and no master not found. usage: follow [FirstName LastName])"; } } @@ -54,6 +54,20 @@ namespace libsecondlife.TestClient return false; } + bool Follow(LLUUID id) + { + foreach (Avatar av in Client.AvatarList.Values) + { + if (av.ID == id) + { + followAvatar = av; + Active = true; + return true; + } + } + return false; + } + public override void Think() { if (Helpers.VecDist(followAvatar.Position, Client.Self.Position) > DISTANCE_BUFFER) diff --git a/libsecondlife/examples/TestClient/Commands/SetMasterCommand.cs b/libsecondlife/examples/TestClient/Commands/SetMasterCommand.cs index 6be17eec..646ecfee 100644 --- a/libsecondlife/examples/TestClient/Commands/SetMasterCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/SetMasterCommand.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using libsecondlife; using libsecondlife.Packets; @@ -9,11 +10,15 @@ namespace libsecondlife.TestClient public class SetMasterCommand: Command { public DateTime Created = DateTime.Now; + private LLUUID resolvedMasterKey = LLUUID.Zero; + private ManualResetEvent keyResolution = new ManualResetEvent(false); + private LLUUID query = LLUUID.Zero; public SetMasterCommand(TestClient testClient) { Name = "setMaster"; Description = "Sets the user name of the master user. The master user can IM to run commands."; + } public override string Execute(string[] args, LLUUID fromAgentID) @@ -21,18 +26,48 @@ namespace libsecondlife.TestClient string masterName = String.Empty; for (int ct = 0; ct < args.Length;ct++) masterName = masterName + args[ct] + " "; - Client.Master = masterName.TrimEnd(); + masterName = masterName.TrimEnd(); + + if (masterName.Length == 0) + return "Usage setMaster name"; + + DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler); + Client.Directory.OnDirPeopleReply += callback; + query = Client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, masterName); + if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false)) + { + Client.MasterKey = resolvedMasterKey; + keyResolution.Reset(); + Client.Directory.OnDirPeopleReply -= callback; + } + else + { + keyResolution.Reset(); + Client.Directory.OnDirPeopleReply -= callback; + return "Unable to obtain UUID for \"" + masterName + "\". Master unchanged."; + } + foreach (Avatar av in Client.AvatarList.Values) { - if (av.Name == Client.Master) + if (av.ID == Client.MasterKey) { Client.Self.InstantMessage(av.ID, "You are now my master. IM me with \"help\" for a command list."); break; } } - return "Master set to " + masterName; + return "Master set to " + masterName + " (" + Client.MasterKey.ToStringHyphenated() + ")"; } + + private void KeyResolvHandler(LLUUID queryid, List matches) + { + if (query != queryid) + return; + // We can't handle ambiguities here as nicely as we can in ClientManager. + resolvedMasterKey = matches[0].AgentID; + keyResolution.Set(); + query = LLUUID.Zero; + } } } diff --git a/libsecondlife/examples/TestClient/Commands/SetMasterKeyCommand.cs b/libsecondlife/examples/TestClient/Commands/SetMasterKeyCommand.cs new file mode 100644 index 00000000..1fa6336e --- /dev/null +++ b/libsecondlife/examples/TestClient/Commands/SetMasterKeyCommand.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; +using libsecondlife; +using libsecondlife.Packets; + +namespace libsecondlife.TestClient +{ + public class SetMasterKeyCommand : Command + { + public DateTime Created = DateTime.Now; + + public SetMasterKeyCommand(TestClient testClient) + { + Name = "setMasterKey"; + Description = "Sets the key of the master user. The master user can IM to run commands."; + } + + public override string Execute(string[] args, LLUUID fromAgentID) + { + Client.MasterKey = LLUUID.Parse(args[0]); + + foreach (Avatar av in Client.AvatarList.Values) + { + if (av.ID == Client.MasterKey) + { + Client.Self.InstantMessage(av.ID, "You are now my master. IM me with \"help\" for a command list."); + break; + } + } + + return "Master set to " + Client.MasterKey; + } + } +} diff --git a/libsecondlife/examples/TestClient/Program.cs b/libsecondlife/examples/TestClient/Program.cs index ed4abd51..705cf90b 100644 --- a/libsecondlife/examples/TestClient/Program.cs +++ b/libsecondlife/examples/TestClient/Program.cs @@ -10,8 +10,8 @@ namespace libsecondlife.TestClient private static void Usage() { Console.WriteLine("Usage: " + Environment.NewLine + - "TestClient.exe --first firstname --last lastname --pass password --contact \"youremail\" [--startpos \"sim/x/y/z\"] [--master \"master name\"]" + - Environment.NewLine + "TestClient.exe --file filename --contact \"youremail\" [--master \"master name\"]"); + "TestClient.exe --first firstname --last lastname --pass password --contact \"youremail\" [--startpos \"sim/x/y/z\"] [--master \"master name\"] [--masterkey \"master uuid\"]" + + Environment.NewLine + "TestClient.exe --file filename --contact \"youremail\" [--master \"master name\"] [--masterkey \"master uuid\"]"); } static void Main(string[] args) @@ -21,13 +21,18 @@ namespace libsecondlife.TestClient ClientManager manager; List accounts = new List(); LoginDetails account; - string master = String.Empty; + string masterName = String.Empty; + LLUUID masterKey = LLUUID.Zero; string file = String.Empty; string contact = String.Empty; + if (arguments["masterkey"] != null) + { + masterKey = LLUUID.Parse(arguments["masterkey"]); + } if (arguments["master"] != null) { - master = arguments["master"]; + masterName = arguments["master"]; } if (arguments["contact"] != null) @@ -103,8 +108,11 @@ namespace libsecondlife.TestClient return; } - foreach (LoginDetails a in accounts) - a.Master = master; + foreach (LoginDetails a in accounts) + { + a.MasterName = masterName; + a.MasterKey = masterKey; + } // Login the accounts and run the input loop if ( arguments["start"] != null ) { diff --git a/libsecondlife/examples/TestClient/TestClient.cs b/libsecondlife/examples/TestClient/TestClient.cs index fafb25b9..5588e5ce 100644 --- a/libsecondlife/examples/TestClient/TestClient.cs +++ b/libsecondlife/examples/TestClient/TestClient.cs @@ -21,7 +21,8 @@ namespace libsecondlife.TestClient public Dictionary Appearances = new Dictionary(); public Dictionary Commands = new Dictionary(); public bool Running = true; - public string Master = String.Empty; + public string MasterName = String.Empty; + public LLUUID MasterKey = LLUUID.Zero; public ClientManager ClientManager; public int regionX; public int regionY; @@ -47,7 +48,7 @@ namespace libsecondlife.TestClient RegisterAllCommands(Assembly.GetExecutingAssembly()); - Settings.DEBUG = false; + Settings.DEBUG = true; Settings.STORE_LAND_PATCHES = true; Settings.ALWAYS_REQUEST_OBJECTS = true; @@ -280,9 +281,9 @@ namespace libsecondlife.TestClient bool groupIM, LLUUID imSessionID, DateTime timestamp, string message, MainAvatar.InstantMessageOnline offline, byte[] binaryBucket) { - if (Master != null && Master.Length > 0) + if (MasterKey != LLUUID.Zero) { - if (fromAgentName.ToLower().Trim() != Master.ToLower().Trim()) + if (fromAgentID != MasterKey) { // Received an IM from someone that is not the bot's master, ignore Console.WriteLine("" + fromAgentName + " (not master): " + message + "@" + regionID.ToString() + ":" + position.ToString() ); diff --git a/libsecondlife/examples/TestClient/TestClient.csproj b/libsecondlife/examples/TestClient/TestClient.csproj index a6153fec..db88e8e8 100644 --- a/libsecondlife/examples/TestClient/TestClient.csproj +++ b/libsecondlife/examples/TestClient/TestClient.csproj @@ -79,6 +79,7 @@ + @@ -115,4 +116,4 @@ --> - \ No newline at end of file + diff --git a/libsecondlife/examples/name2key/name2key.cs b/libsecondlife/examples/name2key/name2key.cs index 01f9bb4b..675238f6 100644 --- a/libsecondlife/examples/name2key/name2key.cs +++ b/libsecondlife/examples/name2key/name2key.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; +using System.Threading; using libsecondlife; using libsecondlife.Packets; @@ -33,28 +34,30 @@ namespace name2key { class name2key { - static bool waiting = true; + private static AutoResetEvent queryEvent = new AutoResetEvent(false); + private static LLUUID queryID = LLUUID.Zero; - public static void QueryHandler(Packet packet, Simulator simulator) - { - DirPeopleReplyPacket reply = (DirPeopleReplyPacket)packet; - - if (reply.QueryReplies.Length < 1) + public static void DirQueryHandler(LLUUID queryid, List results) + { + if (queryID == queryid) { - Console.WriteLine("ERROR: Got an empty reply"); - } - else - { - if (reply.QueryReplies.Length > 1) + if (results.Count < 1) { - Console.WriteLine("ERROR: Ambiguous name. Returning first match"); + Console.WriteLine("ERROR: Got an empty reply"); + } + else + { + if (results.Count > 1) + { + Console.WriteLine("ERROR: Ambiguous name. Returning first match"); + } + + Console.WriteLine("UUID: " + results[0].AgentID.ToString()); } - Console.WriteLine("UUID: " + reply.QueryReplies[0].AgentID.ToString()); + queryEvent.Set(); } - - waiting = false; - } + } /// /// The main entry point for the application. @@ -73,8 +76,7 @@ namespace name2key client = new SecondLife(); // Setup the callback - // FIXME: Rewrite this code as soon as people searching is added to DirectoryManager - client.Network.RegisterCallback(PacketType.DirPeopleReply, new NetworkManager.PacketCallback(QueryHandler)); + client.Directory.OnDirPeopleReply += new DirectoryManager.DirPeopleReplyCallback(DirQueryHandler); if (!client.Network.Login(args[0], args[1], args[2], "name2key", "jhurliman@wsu.edu")) { @@ -84,22 +86,10 @@ namespace name2key } // Send the Query - DirFindQueryPacket find = new DirFindQueryPacket(); - find.AgentData.AgentID = client.Network.AgentID; - find.AgentData.SessionID = client.Network.SessionID; - find.QueryData.QueryFlags = 1; - find.QueryData.QueryText = Helpers.StringToField(args[3] + " " + args[4]); - find.QueryData.QueryID = LLUUID.Random(); - find.QueryData.QueryStart = 0; + queryID = client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, args[3] + " " + args[4]); - client.Network.SendPacket((Packet)find); - - while (waiting) - { - // FIXME: Sleeping while loops are a poor example, this is supposed to be - // model code. Replace this with a ManualResetEvent - System.Threading.Thread.Sleep(500); - } + // Wait for the event to trigger + queryEvent.WaitOne(8000, false); client.Network.Logout(); }