diff options
Diffstat (limited to '')
-rw-r--r-- | ExportBot/ClientManager.cs | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/ExportBot/ClientManager.cs b/ExportBot/ClientManager.cs new file mode 100644 index 0000000..0e43142 --- /dev/null +++ b/ExportBot/ClientManager.cs | |||
@@ -0,0 +1,307 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Reflection; | ||
4 | using System.Xml; | ||
5 | using System.Threading; | ||
6 | using libsecondlife; | ||
7 | using libsecondlife.Packets; | ||
8 | using libsecondlife.AssetSystem; | ||
9 | |||
10 | namespace libsecondlife.TestClient | ||
11 | { | ||
12 | public class LoginDetails | ||
13 | { | ||
14 | public string FirstName; | ||
15 | public string LastName; | ||
16 | public string Password; | ||
17 | public string StartLocation; | ||
18 | public string MasterName; | ||
19 | public LLUUID MasterKey; | ||
20 | } | ||
21 | |||
22 | public class StartPosition | ||
23 | { | ||
24 | public string sim; | ||
25 | public int x; | ||
26 | public int y; | ||
27 | public int z; | ||
28 | |||
29 | public StartPosition() | ||
30 | { | ||
31 | this.sim = null; | ||
32 | this.x = 0; | ||
33 | this.y = 0; | ||
34 | this.z = 0; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | public class ClientManager | ||
39 | { | ||
40 | public Dictionary<LLUUID, SecondLife> Clients = new Dictionary<LLUUID, SecondLife>(); | ||
41 | public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims = new Dictionary<Simulator, Dictionary<uint, Primitive>>(); | ||
42 | |||
43 | public bool Running = true; | ||
44 | |||
45 | string contactPerson = String.Empty; | ||
46 | private LLUUID resolvedMasterKey = LLUUID.Zero; | ||
47 | private ManualResetEvent keyResolution = new ManualResetEvent(false); | ||
48 | |||
49 | /// <summary> | ||
50 | /// | ||
51 | /// </summary> | ||
52 | /// <param name="accounts"></param> | ||
53 | public ClientManager(List<LoginDetails> accounts, string c) | ||
54 | { | ||
55 | this.contactPerson = c; | ||
56 | foreach (LoginDetails account in accounts) | ||
57 | Login(account); | ||
58 | } | ||
59 | |||
60 | public ClientManager(List<LoginDetails> accounts, string c, string s) | ||
61 | { | ||
62 | this.contactPerson = c; | ||
63 | char sep = '/'; | ||
64 | string[] startbits = s.Split(sep); | ||
65 | |||
66 | foreach (LoginDetails account in accounts) | ||
67 | { | ||
68 | account.StartLocation = NetworkManager.StartLocation(startbits[0], Int32.Parse(startbits[1]), | ||
69 | Int32.Parse(startbits[2]), Int32.Parse(startbits[3])); | ||
70 | Login(account); | ||
71 | } | ||
72 | } | ||
73 | /// <summary> | ||
74 | /// | ||
75 | /// </summary> | ||
76 | /// <param name="account"></param> | ||
77 | /// <returns></returns> | ||
78 | public TestClient Login(LoginDetails account) | ||
79 | { | ||
80 | // Check if this client is already logged in | ||
81 | foreach (TestClient c in Clients.Values) | ||
82 | { | ||
83 | if (c.Self.FirstName == account.FirstName && c.Self.LastName == account.LastName) | ||
84 | { | ||
85 | Logout(c); | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | TestClient client = new TestClient(this); | ||
91 | |||
92 | // Optimize the throttle | ||
93 | client.Throttle.Wind = 0; | ||
94 | client.Throttle.Cloud = 0; | ||
95 | client.Throttle.Land = 1000000; | ||
96 | client.Throttle.Task = 1000000; | ||
97 | |||
98 | client.SimPrims = SimPrims; | ||
99 | client.MasterName = account.MasterName; | ||
100 | client.MasterKey = account.MasterKey; | ||
101 | |||
102 | if (!String.IsNullOrEmpty(account.StartLocation)) | ||
103 | { | ||
104 | if (!client.Network.Login(account.FirstName, account.LastName, account.Password, "TestClient", | ||
105 | account.StartLocation, contactPerson)) | ||
106 | { | ||
107 | Console.WriteLine("Failed to login " + account.FirstName + " " + account.LastName + ": " + | ||
108 | client.Network.LoginMessage); | ||
109 | } | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | if (!client.Network.Login(account.FirstName, account.LastName, account.Password, "TestClient", | ||
114 | contactPerson)) | ||
115 | { | ||
116 | Console.WriteLine("Failed to login " + account.FirstName + " " + account.LastName + ": " + | ||
117 | client.Network.LoginStatusMessage); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | if (client.Network.Connected) | ||
122 | { | ||
123 | if (account.MasterKey == LLUUID.Zero && !String.IsNullOrEmpty(account.MasterName)) | ||
124 | { | ||
125 | Console.WriteLine("Resolving {0}'s UUID", account.MasterName); | ||
126 | // Find master's key from name | ||
127 | DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler); | ||
128 | client.Directory.OnDirPeopleReply += callback; | ||
129 | client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, account.MasterName); | ||
130 | if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false)) | ||
131 | { | ||
132 | account.MasterKey = resolvedMasterKey; | ||
133 | Console.WriteLine("\"{0}\" resolved to {1}", account.MasterName, account.MasterKey); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | Console.WriteLine("Unable to obtain UUID for \"{0}\". No master will be used. Try specifying a key with --masterkey.", account.MasterName); | ||
138 | } | ||
139 | client.Directory.OnDirPeopleReply -= callback; | ||
140 | keyResolution.Reset(); | ||
141 | } | ||
142 | |||
143 | client.MasterKey = account.MasterKey; | ||
144 | |||
145 | Clients[client.Network.AgentID] = client; | ||
146 | |||
147 | Console.WriteLine("Logged in " + client.ToString()); | ||
148 | } | ||
149 | |||
150 | return client; | ||
151 | } | ||
152 | |||
153 | private void KeyResolvHandler(LLUUID queryid, List<DirectoryManager.AgentSearchData> matches) | ||
154 | { | ||
155 | LLUUID master = matches[0].AgentID; | ||
156 | if (matches.Count > 1) | ||
157 | { | ||
158 | Console.WriteLine("Possible masters:"); | ||
159 | for (int i = 0; i < matches.Count; ++i) | ||
160 | { | ||
161 | Console.WriteLine("{0}: {1}", i, matches[i].FirstName + " " + matches[i].LastName); | ||
162 | } | ||
163 | Console.Write("Ambiguous master, choose one:"); | ||
164 | string read = Console.ReadLine(); | ||
165 | while (read != null) | ||
166 | { | ||
167 | int choice = 0; | ||
168 | if (int.TryParse(read, out choice)) | ||
169 | { | ||
170 | master = matches[choice].AgentID; | ||
171 | break; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | Console.WriteLine("Responce misunderstood."); | ||
176 | Console.Write("Type the corresponding number:"); | ||
177 | } | ||
178 | read = Console.ReadLine(); | ||
179 | } | ||
180 | } | ||
181 | resolvedMasterKey = master; | ||
182 | keyResolution.Set(); | ||
183 | } | ||
184 | |||
185 | /// <summary> | ||
186 | /// | ||
187 | /// </summary> | ||
188 | /// <param name="args"></param> | ||
189 | /// <returns></returns> | ||
190 | public TestClient Login(string[] args) | ||
191 | { | ||
192 | LoginDetails account = new LoginDetails(); | ||
193 | account.FirstName = args[0]; | ||
194 | account.LastName = args[1]; | ||
195 | account.Password = args[2]; | ||
196 | |||
197 | if (args.Length == 4) | ||
198 | { | ||
199 | account.StartLocation = NetworkManager.StartLocation(args[3], 128, 128, 40); | ||
200 | } | ||
201 | |||
202 | return Login(account); | ||
203 | } | ||
204 | |||
205 | /// <summary> | ||
206 | /// | ||
207 | /// </summary> | ||
208 | public void Run() | ||
209 | { | ||
210 | Console.WriteLine("Type quit to exit. Type help for a command list."); | ||
211 | |||
212 | while (Running) | ||
213 | { | ||
214 | PrintPrompt(); | ||
215 | string input = Console.ReadLine(); | ||
216 | DoCommandAll(input, null, null); | ||
217 | } | ||
218 | |||
219 | foreach (SecondLife client in Clients.Values) | ||
220 | { | ||
221 | if (client.Network.Connected) | ||
222 | client.Network.Logout(); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | private void PrintPrompt() | ||
227 | { | ||
228 | int online = 0; | ||
229 | |||
230 | foreach (SecondLife client in Clients.Values) | ||
231 | { | ||
232 | if (client.Network.Connected) online++; | ||
233 | } | ||
234 | |||
235 | Console.Write(online + " avatars online> "); | ||
236 | } | ||
237 | |||
238 | /// <summary> | ||
239 | /// | ||
240 | /// </summary> | ||
241 | /// <param name="cmd"></param> | ||
242 | /// <param name="fromAgentID"></param> | ||
243 | /// <param name="imSessionID"></param> | ||
244 | public void DoCommandAll(string cmd, LLUUID fromAgentID, LLUUID imSessionID) | ||
245 | { | ||
246 | string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' }); | ||
247 | string firstToken = tokens[0].ToLower(); | ||
248 | |||
249 | if (tokens.Length == 0) | ||
250 | return; | ||
251 | |||
252 | if (firstToken == "login") | ||
253 | { | ||
254 | // Special login case: Only call it once, and allow it with | ||
255 | // no logged in avatars | ||
256 | string[] args = new string[tokens.Length - 1]; | ||
257 | Array.Copy(tokens, 1, args, 0, args.Length); | ||
258 | Login(args); | ||
259 | } | ||
260 | else if (firstToken == "quit") | ||
261 | { | ||
262 | Quit(); | ||
263 | Console.WriteLine("All clients logged out and program finished running."); | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | // make a copy of the clients list so that it can be iterated without fear of being changed during iteration | ||
268 | Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients); | ||
269 | |||
270 | foreach (TestClient client in clientsCopy.Values) | ||
271 | client.DoCommand(cmd, fromAgentID, imSessionID); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /// <summary> | ||
276 | /// | ||
277 | /// </summary> | ||
278 | /// <param name="client"></param> | ||
279 | public void Logout(TestClient client) | ||
280 | { | ||
281 | Clients.Remove(client.Network.AgentID); | ||
282 | client.Network.Logout(); | ||
283 | } | ||
284 | |||
285 | /// <summary> | ||
286 | /// | ||
287 | /// </summary> | ||
288 | public void LogoutAll() | ||
289 | { | ||
290 | // make a copy of the clients list so that it can be iterated without fear of being changed during iteration | ||
291 | Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients); | ||
292 | |||
293 | foreach (TestClient client in clientsCopy.Values) | ||
294 | Logout(client); | ||
295 | } | ||
296 | |||
297 | /// <summary> | ||
298 | /// | ||
299 | /// </summary> | ||
300 | public void Quit() | ||
301 | { | ||
302 | LogoutAll(); | ||
303 | Running = false; | ||
304 | // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit. | ||
305 | } | ||
306 | } | ||
307 | } | ||