corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.Xml;
5 using System.Threading;
6 using OpenMetaverse;
7 using OpenMetaverse.Packets;
8  
9 namespace OpenMetaverse.TestClient
10 {
11 public class LoginDetails
12 {
13 public string FirstName;
14 public string LastName;
15 public string Password;
16 public string StartLocation;
17 public bool GroupCommands;
18 public string MasterName;
19 public UUID MasterKey;
20 public string URI;
21 }
22  
23 public class StartPosition
24 {
25 public string sim;
26 public int x;
27 public int y;
28 public int z;
29  
30 public StartPosition()
31 {
32 this.sim = null;
33 this.x = 0;
34 this.y = 0;
35 this.z = 0;
36 }
37 }
38  
39 public sealed class ClientManager
40 {
41 const string VERSION = "1.0.0";
42  
43 class Singleton { internal static readonly ClientManager Instance = new ClientManager(); }
44 public static ClientManager Instance { get { return Singleton.Instance; } }
45  
46 public Dictionary<UUID, TestClient> Clients = new Dictionary<UUID, TestClient>();
47 public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims = new Dictionary<Simulator, Dictionary<uint, Primitive>>();
48  
49 public bool Running = true;
50 public bool GetTextures = false;
51 public volatile int PendingLogins = 0;
52 public string onlyAvatar = String.Empty;
53  
54 ClientManager()
55 {
56 }
57  
58 public void Start(List<LoginDetails> accounts, bool getTextures)
59 {
60 GetTextures = getTextures;
61  
62 foreach (LoginDetails account in accounts)
63 Login(account);
64 }
65  
66 public TestClient Login(string[] args)
67 {
68 if (args.Length < 3)
69 {
70 Console.WriteLine("Usage: login firstname lastname password [simname] [login server url]");
71 return null;
72 }
73 LoginDetails account = new LoginDetails();
74 account.FirstName = args[0];
75 account.LastName = args[1];
76 account.Password = args[2];
77  
78 if (args.Length > 3)
79 {
80 // If it looks like a full starting position was specified, parse it
81 if (args[3].StartsWith("http"))
82 {
83 account.URI = args[3];
84 }
85 else
86 {
87 if (args[3].IndexOf('/') >= 0)
88 {
89 char sep = '/';
90 string[] startbits = args[3].Split(sep);
91 try
92 {
93 account.StartLocation = NetworkManager.StartLocation(startbits[0], Int32.Parse(startbits[1]),
94 Int32.Parse(startbits[2]), Int32.Parse(startbits[3]));
95 }
96 catch (FormatException) { }
97 }
98  
99 // Otherwise, use the center of the named region
100 if (account.StartLocation == null)
101 account.StartLocation = NetworkManager.StartLocation(args[3], 128, 128, 40);
102 }
103 }
104  
105 if (args.Length > 4)
106 if (args[4].StartsWith("http"))
107 account.URI = args[4];
108  
109 if (string.IsNullOrEmpty(account.URI))
110 account.URI = Program.LoginURI;
111 Logger.Log("Using login URI " + account.URI, Helpers.LogLevel.Info);
112  
113 return Login(account);
114 }
115  
116 public TestClient Login(LoginDetails account)
117 {
118 // Check if this client is already logged in
119 foreach (TestClient c in Clients.Values)
120 {
121 if (c.Self.FirstName == account.FirstName && c.Self.LastName == account.LastName)
122 {
123 Logout(c);
124 break;
125 }
126 }
127  
128 ++PendingLogins;
129  
130 TestClient client = new TestClient(this);
131 client.Network.LoginProgress +=
132 delegate(object sender, LoginProgressEventArgs e)
133 {
134 Logger.Log(String.Format("Login {0}: {1}", e.Status, e.Message), Helpers.LogLevel.Info, client);
135  
136 if (e.Status == LoginStatus.Success)
137 {
138 Clients[client.Self.AgentID] = client;
139  
140 if (client.MasterKey == UUID.Zero)
141 {
142 UUID query = UUID.Zero;
143 EventHandler<DirPeopleReplyEventArgs> peopleDirCallback =
144 delegate(object sender2, DirPeopleReplyEventArgs dpe)
145 {
146 if (dpe.QueryID == query)
147 {
148 if (dpe.MatchedPeople.Count != 1)
149 {
150 Logger.Log("Unable to resolve master key from " + client.MasterName, Helpers.LogLevel.Warning);
151 }
152 else
153 {
154 client.MasterKey = dpe.MatchedPeople[0].AgentID;
155 Logger.Log("Master key resolved to " + client.MasterKey, Helpers.LogLevel.Info);
156 }
157 }
158 };
159  
160 client.Directory.DirPeopleReply += peopleDirCallback;
161 query = client.Directory.StartPeopleSearch(client.MasterName, 0);
162 }
163  
164 Logger.Log("Logged in " + client.ToString(), Helpers.LogLevel.Info);
165 --PendingLogins;
166 }
167 else if (e.Status == LoginStatus.Failed)
168 {
169 Logger.Log("Failed to login " + account.FirstName + " " + account.LastName + ": " +
170 client.Network.LoginMessage, Helpers.LogLevel.Warning);
171 --PendingLogins;
172 }
173 };
174  
175 // Optimize the throttle
176 client.Throttle.Wind = 0;
177 client.Throttle.Cloud = 0;
178 client.Throttle.Land = 1000000;
179 client.Throttle.Task = 1000000;
180  
181 client.GroupCommands = account.GroupCommands;
182 client.MasterName = account.MasterName;
183 client.MasterKey = account.MasterKey;
184 client.AllowObjectMaster = client.MasterKey != UUID.Zero; // Require UUID for object master.
185  
186 LoginParams loginParams = client.Network.DefaultLoginParams(
187 account.FirstName, account.LastName, account.Password, "TestClient", VERSION);
188  
189 if (!String.IsNullOrEmpty(account.StartLocation))
190 loginParams.Start = account.StartLocation;
191  
192 if (!String.IsNullOrEmpty(account.URI))
193 loginParams.URI = account.URI;
194  
195 client.Network.BeginLogin(loginParams);
196 return client;
197 }
198  
199 /// <summary>
200 ///
201 /// </summary>
202 public void Run(bool noGUI)
203 {
204 if (noGUI)
205 {
206 while (Running)
207 {
208 Thread.Sleep(2 * 1000);
209 }
210 }
211 else {
212 Console.WriteLine("Type quit to exit. Type help for a command list.");
213  
214 while (Running)
215 {
216 PrintPrompt();
217 string input = Console.ReadLine();
218 DoCommandAll(input, UUID.Zero);
219 }
220 }
221  
222 foreach (GridClient client in Clients.Values)
223 {
224 if (client.Network.Connected)
225 client.Network.Logout();
226 }
227 }
228  
229 private void PrintPrompt()
230 {
231 int online = 0;
232  
233 foreach (GridClient client in Clients.Values)
234 {
235 if (client.Network.Connected) online++;
236 }
237  
238 Console.Write(online + " avatars online> ");
239 }
240  
241 /// <summary>
242 ///
243 /// </summary>
244 /// <param name="cmd"></param>
245 /// <param name="fromAgentID"></param>
246 /// <param name="imSessionID"></param>
247 public void DoCommandAll(string cmd, UUID fromAgentID)
248 {
249 string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' });
250 if (tokens.Length == 0)
251 return;
252  
253 string firstToken = tokens[0].ToLower();
254 if (String.IsNullOrEmpty(firstToken))
255 return;
256  
257 // Allow for comments when cmdline begins with ';' or '#'
258 if (firstToken[0] == ';' || firstToken[0] == '#')
259 return;
260  
261 if ('@' == firstToken[0]) {
262 onlyAvatar = String.Empty;
263 if (tokens.Length == 3) {
264 bool found = false;
265 onlyAvatar = tokens[1]+" "+tokens[2];
266 foreach (TestClient client in Clients.Values) {
267 if ((client.ToString() == onlyAvatar) && (client.Network.Connected)) {
268 found = true;
269 break;
270 }
271 }
272 if (found) {
273 Logger.Log("Commanding only "+onlyAvatar+" now", Helpers.LogLevel.Info);
274 } else {
275 Logger.Log("Commanding nobody now. Avatar "+onlyAvatar+" is offline", Helpers.LogLevel.Info);
276 }
277 } else {
278 Logger.Log("Commanding all avatars now", Helpers.LogLevel.Info);
279 }
280 return;
281 }
282  
283 string[] args = new string[tokens.Length - 1];
284 if (args.Length > 0)
285 Array.Copy(tokens, 1, args, 0, args.Length);
286  
287 if (firstToken == "login")
288 {
289 Login(args);
290 }
291 else if (firstToken == "quit")
292 {
293 Quit();
294 Logger.Log("All clients logged out and program finished running.", Helpers.LogLevel.Info);
295 }
296 else if (firstToken == "help")
297 {
298 if (Clients.Count > 0)
299 {
300 foreach (TestClient client in Clients.Values)
301 {
302 Console.WriteLine(client.Commands["help"].Execute(args, UUID.Zero));
303 break;
304 }
305 }
306 else
307 {
308 Console.WriteLine("You must login at least one bot to use the help command");
309 }
310 }
311 else if (firstToken == "script")
312 {
313 // No reason to pass this to all bots, and we also want to allow it when there are no bots
314 ScriptCommand command = new ScriptCommand(null);
315 Logger.Log(command.Execute(args, UUID.Zero), Helpers.LogLevel.Info);
316 }
317 else if (firstToken == "waitforlogin")
318 {
319 // Special exception to allow this to run before any bots have logged in
320 if (ClientManager.Instance.PendingLogins > 0)
321 {
322 WaitForLoginCommand command = new WaitForLoginCommand(null);
323 Logger.Log(command.Execute(args, UUID.Zero), Helpers.LogLevel.Info);
324 }
325 else
326 {
327 Logger.Log("No pending logins", Helpers.LogLevel.Info);
328 }
329 }
330 else
331 {
332 // Make an immutable copy of the Clients dictionary to safely iterate over
333 Dictionary<UUID, TestClient> clientsCopy = new Dictionary<UUID, TestClient>(Clients);
334  
335 int completed = 0;
336  
337 foreach (TestClient client in clientsCopy.Values)
338 {
339 ThreadPool.QueueUserWorkItem((WaitCallback)
340 delegate(object state)
341 {
342 TestClient testClient = (TestClient)state;
343 if ((String.Empty == onlyAvatar) || (testClient.ToString() == onlyAvatar)) {
344 if (testClient.Commands.ContainsKey(firstToken)) {
345 string result;
346 try {
347 result = testClient.Commands[firstToken].Execute(args, fromAgentID);
348 Logger.Log(result, Helpers.LogLevel.Info, testClient);
349 } catch(Exception e) {
350 Logger.Log(String.Format("{0} raised exception {1}", firstToken, e),
351 Helpers.LogLevel.Error,
352 testClient);
353 }
354 } else
355 Logger.Log("Unknown command " + firstToken, Helpers.LogLevel.Warning);
356 }
357  
358 ++completed;
359 },
360 client);
361 }
362  
363 while (completed < clientsCopy.Count)
364 Thread.Sleep(50);
365 }
366 }
367  
368 /// <summary>
369 ///
370 /// </summary>
371 /// <param name="client"></param>
372 public void Logout(TestClient client)
373 {
374 Clients.Remove(client.Self.AgentID);
375 client.Network.Logout();
376 }
377  
378 /// <summary>
379 ///
380 /// </summary>
381 public void Quit()
382 {
383 Running = false;
384 // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit.
385 }
386 }
387 }