aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAdam Frisby2007-06-21 17:08:21 +0000
committerAdam Frisby2007-06-21 17:08:21 +0000
commite93869c7a785a4f375685ffa33c913033ed1c85a (patch)
treeabb5e2c58f8750a1bc05acf58716b6b025da4d15
parentFixed the struct and null compare bug. (diff)
downloadopensim-SC-e93869c7a785a4f375685ffa33c913033ed1c85a.zip
opensim-SC-e93869c7a785a4f375685ffa33c913033ed1c85a.tar.gz
opensim-SC-e93869c7a785a4f375685ffa33c913033ed1c85a.tar.bz2
opensim-SC-e93869c7a785a4f375685ffa33c913033ed1c85a.tar.xz
* Importing Ming's mass test client
-rw-r--r--tools/mass test client/Arguments.cs111
-rw-r--r--tools/mass test client/ClientManager.cs323
-rw-r--r--tools/mass test client/Command.cs29
-rw-r--r--tools/mass test client/Commands/CloneProfileCommand.cs131
-rw-r--r--tools/mass test client/Commands/Communication/EchoMasterCommand.cs42
-rw-r--r--tools/mass test client/Commands/Communication/IMCommand.cs71
-rw-r--r--tools/mass test client/Commands/Communication/SayCommand.cs44
-rw-r--r--tools/mass test client/Commands/Communication/ShoutCommand.cs49
-rw-r--r--tools/mass test client/Commands/Communication/TtsCommand.cs51
-rw-r--r--tools/mass test client/Commands/Communication/WhisperCommand.cs49
-rw-r--r--tools/mass test client/Commands/GoHome.cs26
-rw-r--r--tools/mass test client/Commands/GotoLandmark.cs32
-rw-r--r--tools/mass test client/Commands/Inventory/AppearanceCommand.cs29
-rw-r--r--tools/mass test client/Commands/Inventory/BalanceCommand.cs21
-rw-r--r--tools/mass test client/Commands/Inventory/DeleteFolderCommand.cs43
-rw-r--r--tools/mass test client/Commands/Inventory/DumpOutfitCommand.cs98
-rw-r--r--tools/mass test client/Commands/Inventory/ExportOutfitCommand.cs66
-rw-r--r--tools/mass test client/Commands/Inventory/GiveAllCommand.cs27
-rw-r--r--tools/mass test client/Commands/Inventory/ImportOutfitCommand.cs66
-rw-r--r--tools/mass test client/Commands/Inventory/InventoryCommand.cs62
-rw-r--r--tools/mass test client/Commands/Inventory/WearCommand.cs43
-rw-r--r--tools/mass test client/Commands/Land/FindSimCommand.cs43
-rw-r--r--tools/mass test client/Commands/Land/ParcelInfoCommand.cs62
-rw-r--r--tools/mass test client/Commands/Movement/FollowCommand.cs90
-rw-r--r--tools/mass test client/Commands/Movement/GotoCommand.cs53
-rw-r--r--tools/mass test client/Commands/Movement/JumpCommand.cs34
-rw-r--r--tools/mass test client/Commands/Movement/LocationCommand.cs23
-rw-r--r--tools/mass test client/Commands/Movement/MoveToCommand.cs24
-rw-r--r--tools/mass test client/Commands/Movement/SetHome.cs23
-rw-r--r--tools/mass test client/Commands/Movement/SitCommand.cs52
-rw-r--r--tools/mass test client/Commands/Movement/SitOnCommand.cs54
-rw-r--r--tools/mass test client/Commands/Movement/StandCommand.cs47
-rw-r--r--tools/mass test client/Commands/Prims/ExportCommand.cs209
-rw-r--r--tools/mass test client/Commands/Prims/ExportParticlesCommand.cs119
-rw-r--r--tools/mass test client/Commands/Prims/ImportCommand.cs246
-rw-r--r--tools/mass test client/Commands/Prims/PrimCountCommand.cs32
-rw-r--r--tools/mass test client/Commands/Stats/DilationCommand.cs22
-rw-r--r--tools/mass test client/Commands/Stats/RegionInfoCommand.cs45
-rw-r--r--tools/mass test client/Commands/Stats/StatsCommand.cs44
-rw-r--r--tools/mass test client/Commands/Stats/UptimeCommand.cs25
-rw-r--r--tools/mass test client/Commands/System/DebugCommand.cs37
-rw-r--r--tools/mass test client/Commands/System/HelpCommand.cs29
-rw-r--r--tools/mass test client/Commands/System/LoadCommand.cs28
-rw-r--r--tools/mass test client/Commands/System/LoginCommand.cs34
-rw-r--r--tools/mass test client/Commands/System/LogoutCommand.cs24
-rw-r--r--tools/mass test client/Commands/System/MD5Command.cs22
-rw-r--r--tools/mass test client/Commands/System/PacketLogCommand.cs84
-rw-r--r--tools/mass test client/Commands/System/QuitCommand.cs24
-rw-r--r--tools/mass test client/Commands/System/SetMasterCommand.cs73
-rw-r--r--tools/mass test client/Commands/System/SetMasterKeyCommand.cs35
-rw-r--r--tools/mass test client/Commands/System/ShowEffectsCommand.cs76
-rw-r--r--tools/mass test client/Commands/TouchCommand.cs55
-rw-r--r--tools/mass test client/Commands/TreeCommand.cs51
-rw-r--r--tools/mass test client/Commands/WhoCommand.cs29
-rw-r--r--tools/mass test client/MassTestClient.csproj121
-rw-r--r--tools/mass test client/MassTestClient.csproj.user10
-rw-r--r--tools/mass test client/MassTestClient.sln20
-rw-r--r--tools/mass test client/MassTestClient.suobin0 -> 32256 bytes
-rw-r--r--tools/mass test client/Parsing.cs61
-rw-r--r--tools/mass test client/Program.cs218
-rw-r--r--tools/mass test client/Properties/AssemblyInfo.cs33
-rw-r--r--tools/mass test client/TestClient.build125
-rw-r--r--tools/mass test client/TestClient.cs324
-rw-r--r--tools/mass test client/bin/libsecondlife.Utilities.dllbin0 -> 65536 bytes
-rw-r--r--tools/mass test client/bin/libsecondlife.dllbin0 -> 2256896 bytes
-rw-r--r--tools/mass test client/bin/openjpegnet.dllbin0 -> 32768 bytes
66 files changed, 4173 insertions, 0 deletions
diff --git a/tools/mass test client/Arguments.cs b/tools/mass test client/Arguments.cs
new file mode 100644
index 0000000..302ae95
--- /dev/null
+++ b/tools/mass test client/Arguments.cs
@@ -0,0 +1,111 @@
1using System;
2using System.Collections.Specialized;
3using System.Text.RegularExpressions;
4
5namespace CommandLine.Utility
6{
7 /// <summary>
8 /// Arguments class
9 /// </summary>
10 public class Arguments
11 {
12 // Variables
13 private StringDictionary Parameters;
14
15 // Constructor
16 public Arguments(string[] Args)
17 {
18 Parameters = new StringDictionary();
19 Regex Splitter = new Regex(@"^-{1,2}|=|:",
20 RegexOptions.IgnoreCase | RegexOptions.Compiled);
21
22 Regex Remover = new Regex(@"^['""]?(.*?)['""]?$",
23 RegexOptions.IgnoreCase | RegexOptions.Compiled);
24
25 string Parameter = null;
26 string[] Parts;
27
28 // Valid parameters forms:
29 // {-,/,--}param{ ,=,:}((",')value(",'))
30 // Examples:
31 // -param1 value1 --param2 /param3:"Test-:-work"
32 // /param4=happy -param5 '--=nice=--'
33 foreach (string Txt in Args)
34 {
35 // Look for new parameters (-,/ or --) and a
36 // possible enclosed value (=,:)
37 Parts = Splitter.Split(Txt, 3);
38
39 switch (Parts.Length)
40 {
41 // Found a value (for the last parameter
42 // found (space separator))
43 case 1:
44 if (Parameter != null)
45 {
46 if (!Parameters.ContainsKey(Parameter))
47 {
48 Parts[0] =
49 Remover.Replace(Parts[0], "$1");
50
51 Parameters.Add(Parameter, Parts[0]);
52 }
53 Parameter = null;
54 }
55 // else Error: no parameter waiting for a value (skipped)
56 break;
57
58 // Found just a parameter
59 case 2:
60 // The last parameter is still waiting.
61 // With no value, set it to true.
62 if (Parameter != null)
63 {
64 if (!Parameters.ContainsKey(Parameter))
65 Parameters.Add(Parameter, "true");
66 }
67 Parameter = Parts[1];
68 break;
69
70 // Parameter with enclosed value
71 case 3:
72 // The last parameter is still waiting.
73 // With no value, set it to true.
74 if (Parameter != null)
75 {
76 if (!Parameters.ContainsKey(Parameter))
77 Parameters.Add(Parameter, "true");
78 }
79
80 Parameter = Parts[1];
81
82 // Remove possible enclosing characters (",')
83 if (!Parameters.ContainsKey(Parameter))
84 {
85 Parts[2] = Remover.Replace(Parts[2], "$1");
86 Parameters.Add(Parameter, Parts[2]);
87 }
88
89 Parameter = null;
90 break;
91 }
92 }
93 // In case a parameter is still waiting
94 if (Parameter != null)
95 {
96 if (!Parameters.ContainsKey(Parameter))
97 Parameters.Add(Parameter, "true");
98 }
99 }
100
101 // Retrieve a parameter value if it exists
102 // (overriding C# indexer property)
103 public string this[string Param]
104 {
105 get
106 {
107 return (Parameters[Param]);
108 }
109 }
110 }
111}
diff --git a/tools/mass test client/ClientManager.cs b/tools/mass test client/ClientManager.cs
new file mode 100644
index 0000000..a6e784c
--- /dev/null
+++ b/tools/mass test client/ClientManager.cs
@@ -0,0 +1,323 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.Xml;
5using System.Threading;
6using libsecondlife;
7using libsecondlife.Packets;
8using libsecondlife.AssetSystem;
9
10namespace 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 public string LoginURI;
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 class ClientManager
40 {
41 public Dictionary<LLUUID, SecondLife> Clients = new Dictionary<LLUUID, SecondLife>();
42 public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims = new Dictionary<Simulator, Dictionary<uint, Primitive>>();
43
44 public bool Running = true;
45
46 string contactPerson = String.Empty;
47 private LLUUID resolvedMasterKey = LLUUID.Zero;
48 private ManualResetEvent keyResolution = new ManualResetEvent(false);
49
50 /// <summary>
51 ///
52 /// </summary>
53 /// <param name="accounts"></param>
54 public ClientManager(List<LoginDetails> accounts, string c)
55 {
56 this.contactPerson = c;
57 foreach (LoginDetails account in accounts)
58 Login(account);
59 }
60
61 public ClientManager(List<LoginDetails> accounts, string c, string s)
62 {
63 this.contactPerson = c;
64 char sep = '/';
65 string[] startbits = s.Split(sep);
66
67 foreach (LoginDetails account in accounts)
68 {
69 account.StartLocation = NetworkManager.StartLocation(startbits[0], Int32.Parse(startbits[1]),
70 Int32.Parse(startbits[2]), Int32.Parse(startbits[3]));
71 Login(account);
72 }
73 }
74 /// <summary>
75 ///
76 /// </summary>
77 /// <param name="account"></param>
78 /// <returns></returns>
79 public TestClient Login(LoginDetails account)
80 {
81
82 // Check if this client is already logged in
83 foreach (TestClient c in Clients.Values)
84 {
85 if (c.Self.FirstName == account.FirstName && c.Self.LastName == account.LastName)
86 {
87 Logout(c);
88 break;
89 }
90 }
91
92 TestClient client = new TestClient(this);
93
94 // Optimize the throttle
95 client.Throttle.Wind = 0;
96 client.Throttle.Cloud = 0;
97 client.Throttle.Land = 1000000;
98 client.Throttle.Task = 1000000;
99
100 client.SimPrims = SimPrims;
101 client.MasterName = account.MasterName;
102 client.MasterKey = account.MasterKey;
103
104 libsecondlife.NetworkManager.LoginParams loginParams = new NetworkManager.LoginParams();
105 loginParams.FirstName = account.FirstName;
106 loginParams.LastName = account.LastName;
107 loginParams.Password = account.Password;
108 loginParams.UserAgent = "MassTestClient";
109 loginParams.Start = account.StartLocation;
110 loginParams.Author = contactPerson;
111 loginParams.URI = account.LoginURI;
112
113
114 if (!client.Network.Login(loginParams))
115 {
116 Console.WriteLine("Failed to login " + account.FirstName + " " + account.LastName + ": " +
117 client.Network.LoginMessage);
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, 0);
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(List<string> massTestCommands)
209 {
210 Console.WriteLine("Type quit to exit. Type help for a command list.");
211
212 if (massTestCommands.Count == 0)
213 {
214 while (Running)
215 {
216 PrintPrompt();
217 string input = Console.ReadLine();
218 DoCommandAll(input, null, null);
219 }
220 }
221 else
222 {
223 int currentCommand = 0;
224 while (Running)
225 {
226 DoCommandAll(massTestCommands[currentCommand], null, null);
227 currentCommand++;
228 if (massTestCommands.Count >= currentCommand)
229 {
230 currentCommand = 0;
231 }
232 }
233 }
234
235 foreach (SecondLife client in Clients.Values)
236 {
237 if (client.Network.Connected)
238 client.Network.Logout();
239 }
240 }
241
242 private void PrintPrompt()
243 {
244 int online = 0;
245
246 foreach (SecondLife client in Clients.Values)
247 {
248 if (client.Network.Connected) online++;
249 }
250
251 Console.Write(online + " avatars online> ");
252 }
253
254 /// <summary>
255 ///
256 /// </summary>
257 /// <param name="cmd"></param>
258 /// <param name="fromAgentID"></param>
259 /// <param name="imSessionID"></param>
260 public void DoCommandAll(string cmd, LLUUID fromAgentID, LLUUID imSessionID)
261 {
262 string[] tokens = cmd.Trim().Split(new char[] { ' ', '\t' });
263 string firstToken = tokens[0].ToLower();
264
265 if (tokens.Length == 0)
266 return;
267
268 if (firstToken == "login")
269 {
270 // Special login case: Only call it once, and allow it with
271 // no logged in avatars
272 string[] args = new string[tokens.Length - 1];
273 Array.Copy(tokens, 1, args, 0, args.Length);
274 Login(args);
275 }
276 else if (firstToken == "quit")
277 {
278 Quit();
279 Console.WriteLine("All clients logged out and program finished running.");
280 }
281 else
282 {
283 // make a copy of the clients list so that it can be iterated without fear of being changed during iteration
284 Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients);
285
286 foreach (TestClient client in clientsCopy.Values)
287 client.DoCommand(cmd, fromAgentID, imSessionID);
288 }
289 }
290
291 /// <summary>
292 ///
293 /// </summary>
294 /// <param name="client"></param>
295 public void Logout(TestClient client)
296 {
297 Clients.Remove(client.Network.AgentID);
298 client.Network.Logout();
299 }
300
301 /// <summary>
302 ///
303 /// </summary>
304 public void LogoutAll()
305 {
306 // make a copy of the clients list so that it can be iterated without fear of being changed during iteration
307 Dictionary<LLUUID, SecondLife> clientsCopy = new Dictionary<LLUUID, SecondLife>(Clients);
308
309 foreach (TestClient client in clientsCopy.Values)
310 Logout(client);
311 }
312
313 /// <summary>
314 ///
315 /// </summary>
316 public void Quit()
317 {
318 LogoutAll();
319 Running = false;
320 // TODO: It would be really nice if we could figure out a way to abort the ReadLine here in so that Run() will exit.
321 }
322 }
323}
diff --git a/tools/mass test client/Command.cs b/tools/mass test client/Command.cs
new file mode 100644
index 0000000..051519d
--- /dev/null
+++ b/tools/mass test client/Command.cs
@@ -0,0 +1,29 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public abstract class Command
10 {
11 public string Name;
12 public string Description;
13 public TestClient Client;
14
15 public abstract string Execute(string[] args, LLUUID fromAgentID);
16
17 /// <summary>
18 /// When set to true, think will be called.
19 /// </summary>
20 public bool Active;
21
22 /// <summary>
23 /// Called twice per second, when Command.Active is set to true.
24 /// </summary>
25 public virtual void Think()
26 {
27 }
28 }
29}
diff --git a/tools/mass test client/Commands/CloneProfileCommand.cs b/tools/mass test client/Commands/CloneProfileCommand.cs
new file mode 100644
index 0000000..e475655
--- /dev/null
+++ b/tools/mass test client/Commands/CloneProfileCommand.cs
@@ -0,0 +1,131 @@
1using System;
2using System.Collections.Generic;
3using System.Threading;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class CloneProfileCommand : Command
10 {
11 Avatar.AvatarProperties Properties;
12 Avatar.Interests Interests;
13 List<LLUUID> Groups = new List<LLUUID>();
14 bool ReceivedProperties = false;
15 bool ReceivedInterests = false;
16 bool ReceivedGroups = false;
17 ManualResetEvent ReceivedProfileEvent = new ManualResetEvent(false);
18
19 public CloneProfileCommand(TestClient testClient)
20 {
21 testClient.Avatars.OnAvatarInterests += new AvatarManager.AvatarInterestsCallback(Avatars_OnAvatarInterests);
22 testClient.Avatars.OnAvatarProperties += new AvatarManager.AvatarPropertiesCallback(Avatars_OnAvatarProperties);
23 testClient.Avatars.OnAvatarGroups += new AvatarManager.AvatarGroupsCallback(Avatars_OnAvatarGroups);
24 testClient.Self.OnJoinGroup += new MainAvatar.JoinGroupCallback(Self_OnJoinGroup);
25
26 Name = "cloneprofile";
27 Description = "Clones another avatars profile as closely as possible. WARNING: This command will " +
28 "destroy your existing profile! Usage: cloneprofile [targetuuid]";
29 }
30
31 public override string Execute(string[] args, LLUUID fromAgentID)
32 {
33 if (args.Length != 1)
34 return Description;
35
36 LLUUID targetID;
37 ReceivedProperties = false;
38 ReceivedInterests = false;
39 ReceivedGroups = false;
40
41 try
42 {
43 targetID = new LLUUID(args[0]);
44 }
45 catch (Exception)
46 {
47 return Description;
48 }
49
50 // Request all of the packets that make up an avatar profile
51 Client.Avatars.RequestAvatarProperties(targetID);
52
53 // Wait for all the packets to arrive
54 ReceivedProfileEvent.Reset();
55 ReceivedProfileEvent.WaitOne(5000, false);
56
57 // Check if everything showed up
58 if (!ReceivedInterests || !ReceivedProperties || !ReceivedGroups)
59 return "Failed to retrieve a complete profile for that UUID";
60
61 // Synchronize our profile
62 Client.Self.ProfileInterests = Interests;
63 Client.Self.ProfileProperties = Properties;
64 Client.Self.SetAvatarInformation();
65
66 // TODO: Leave all the groups we're currently a member of? This could
67 // break TestClient connectivity that might be relying on group authentication
68
69 // Attempt to join all the groups
70 foreach (LLUUID groupID in Groups)
71 {
72 Client.Self.RequestJoinGroup(groupID);
73 }
74
75 return "Synchronized our profile to the profile of " + targetID.ToStringHyphenated();
76 }
77
78 void Avatars_OnAvatarProperties(LLUUID avatarID, Avatar.AvatarProperties properties)
79 {
80 lock (ReceivedProfileEvent)
81 {
82 Properties = properties;
83 ReceivedProperties = true;
84
85 if (ReceivedInterests && ReceivedProperties && ReceivedGroups)
86 ReceivedProfileEvent.Set();
87 }
88 }
89
90 void Avatars_OnAvatarInterests(LLUUID avatarID, Avatar.Interests interests)
91 {
92 lock (ReceivedProfileEvent)
93 {
94 Interests = interests;
95 ReceivedInterests = true;
96
97 if (ReceivedInterests && ReceivedProperties && ReceivedGroups)
98 ReceivedProfileEvent.Set();
99 }
100 }
101
102 void Avatars_OnAvatarGroups(LLUUID avatarID, AvatarGroupsReplyPacket.GroupDataBlock[] groups)
103 {
104 lock (ReceivedProfileEvent)
105 {
106 foreach (AvatarGroupsReplyPacket.GroupDataBlock block in groups)
107 {
108 Groups.Add(block.GroupID);
109 }
110
111 ReceivedGroups = true;
112
113 if (ReceivedInterests && ReceivedProperties && ReceivedGroups)
114 ReceivedProfileEvent.Set();
115 }
116 }
117
118 void Self_OnJoinGroup(LLUUID groupID, bool success)
119 {
120 Console.WriteLine(Client.ToString() + (success ? " joined " : " failed to join ") +
121 groupID.ToStringHyphenated());
122
123 if (success)
124 {
125 Console.WriteLine(Client.ToString() + " setting " + groupID.ToStringHyphenated() +
126 " as the active group");
127 Client.Self.ActivateGroup(groupID);
128 }
129 }
130 }
131}
diff --git a/tools/mass test client/Commands/Communication/EchoMasterCommand.cs b/tools/mass test client/Commands/Communication/EchoMasterCommand.cs
new file mode 100644
index 0000000..a7c3d3f
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/EchoMasterCommand.cs
@@ -0,0 +1,42 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class EchoMasterCommand: Command
10 {
11 public EchoMasterCommand(TestClient testClient)
12 {
13 Name = "echoMaster";
14 Description = "Repeat everything that master says.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (!Active)
20 {
21 Active = true;
22 Client.Self.OnChat += new MainAvatar.ChatCallback(Self_OnChat);
23 return "Echoing is now on.";
24 }
25 else
26 {
27 Active = false;
28 Client.Self.OnChat -= new MainAvatar.ChatCallback(Self_OnChat);
29 return "Echoing is now off.";
30 }
31 }
32
33 void Self_OnChat(string message, MainAvatar.ChatAudibleLevel audible, MainAvatar.ChatType type,
34 MainAvatar.ChatSourceType sourcetype, string fromName, LLUUID id, LLUUID ownerid, LLVector3 position)
35 {
36 if (message.Length > 0 && Client.MasterKey == id)
37 {
38 Client.Self.Chat(message, 0, MainAvatar.ChatType.Normal);
39 }
40 }
41 }
42}
diff --git a/tools/mass test client/Commands/Communication/IMCommand.cs b/tools/mass test client/Commands/Communication/IMCommand.cs
new file mode 100644
index 0000000..d847291
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/IMCommand.cs
@@ -0,0 +1,71 @@
1using System;
2using System.Collections.Generic;
3using System.Threading;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class ImCommand : Command
10 {
11 string ToAvatarName = String.Empty;
12 ManualResetEvent NameSearchEvent = new ManualResetEvent(false);
13 Dictionary<string, LLUUID> Name2Key = new Dictionary<string, LLUUID>();
14
15 public ImCommand(TestClient testClient)
16 {
17 testClient.Avatars.OnAvatarNameSearch += new AvatarManager.AvatarNameSearchCallback(Avatars_OnAvatarNameSearch);
18
19 Name = "im";
20 Description = "Instant message someone. Usage: im [firstname] [lastname] [message]";
21 }
22
23 public override string Execute(string[] args, LLUUID fromAgentID)
24 {
25 if (args.Length < 3)
26 return "Usage: im [firstname] [lastname] [message]";
27
28 ToAvatarName = args[0] + " " + args[1];
29
30 // Build the message
31 string message = String.Empty;
32 for (int ct = 2; ct < args.Length; ct++)
33 message += args[ct] + " ";
34 message = message.TrimEnd();
35 if (message.Length > 1023) message = message.Remove(1023);
36
37 if (!Name2Key.ContainsKey(ToAvatarName.ToLower()))
38 {
39 // Send the Query
40 Client.Avatars.RequestAvatarNameSearch(ToAvatarName, LLUUID.Random());
41
42 NameSearchEvent.WaitOne(6000, false);
43 }
44
45 if (Name2Key.ContainsKey(ToAvatarName.ToLower()))
46 {
47 LLUUID id = Name2Key[ToAvatarName.ToLower()];
48
49 Client.Self.InstantMessage(id, message, id);
50 return "Instant Messaged " + id.ToStringHyphenated() + " with message: " + message;
51 }
52 else
53 {
54 return "Name lookup for " + ToAvatarName + " failed";
55 }
56 }
57
58 void Avatars_OnAvatarNameSearch(LLUUID queryID, Dictionary<LLUUID, string> avatars)
59 {
60 foreach (KeyValuePair<LLUUID, string> kvp in avatars)
61 {
62 if (kvp.Value.ToLower() == ToAvatarName.ToLower())
63 {
64 Name2Key[ToAvatarName.ToLower()] = kvp.Key;
65 NameSearchEvent.Set();
66 return;
67 }
68 }
69 }
70 }
71}
diff --git a/tools/mass test client/Commands/Communication/SayCommand.cs b/tools/mass test client/Commands/Communication/SayCommand.cs
new file mode 100644
index 0000000..2ab9db4
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/SayCommand.cs
@@ -0,0 +1,44 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5
6namespace libsecondlife.TestClient
7{
8 public class SayCommand: Command
9 {
10 public SayCommand(TestClient testClient)
11 {
12 Name = "say";
13 Description = "Say something. (usage: say (optional channel) whatever)";
14 }
15
16 public override string Execute(string[] args, LLUUID fromAgentID)
17 {
18 int channel = 0;
19 int startIndex = 0;
20
21 if (args.Length < 1)
22 {
23 return "usage: say (optional channel) whatever";
24 }
25 else if (args.Length > 1)
26 {
27 if (Int32.TryParse(args[0], out channel))
28 startIndex = 1;
29 }
30
31 StringBuilder message = new StringBuilder();
32
33 for (int i = startIndex; i < args.Length; i++)
34 {
35 message.Append(args[i]);
36 if (i != args.Length - 1) message.Append(" ");
37 }
38
39 Client.Self.Chat(message.ToString(), channel, MainAvatar.ChatType.Normal);
40
41 return "Said " + message.ToString();
42 }
43 }
44}
diff --git a/tools/mass test client/Commands/Communication/ShoutCommand.cs b/tools/mass test client/Commands/Communication/ShoutCommand.cs
new file mode 100644
index 0000000..3533e3d
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/ShoutCommand.cs
@@ -0,0 +1,49 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class ShoutCommand : Command
10 {
11 public ShoutCommand(TestClient testClient)
12 {
13 Name = "shout";
14 Description = "Shout something.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 int channel = 0;
20 int startIndex = 0;
21 string message = String.Empty;
22 if (args.Length < 1)
23 {
24 return "usage: shout (optional channel) whatever";
25 }
26 else if (args.Length > 1)
27 {
28 try
29 {
30 channel = Convert.ToInt32(args[0]);
31 startIndex = 1;
32 }
33 catch (FormatException)
34 {
35 channel = 0;
36 }
37 }
38
39 for (int i = startIndex; i < args.Length; i++)
40 {
41 message += args[i] + " ";
42 }
43
44 Client.Self.Chat(message, channel, MainAvatar.ChatType.Shout);
45
46 return "Shouted " + message;
47 }
48 }
49}
diff --git a/tools/mass test client/Commands/Communication/TtsCommand.cs b/tools/mass test client/Commands/Communication/TtsCommand.cs
new file mode 100644
index 0000000..52b7a39
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/TtsCommand.cs
@@ -0,0 +1,51 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Speech.Synthesis;
5using libsecondlife;
6using libsecondlife.Packets;
7using libsecondlife.AssetSystem;
8
9
10// Since this requires .Net 3.0 I've left it out of the project by default.
11// To use this: include it in the project and add a reference to the System.Speech.dll
12
13namespace libsecondlife.TestClient
14{
15 public class TtsCommand : Command
16 {
17 SpeechSynthesizer _speechSynthesizer;
18
19 public TtsCommand(TestClient testClient)
20 {
21 Name = "tts";
22 Description = "Text To Speech. When activated, client will echo all recieved chat messages out thru the computer's speakers.";
23 }
24
25 public override string Execute(string[] args, LLUUID fromAgentID)
26 {
27 if (!Active)
28 {
29 if (_speechSynthesizer == null)
30 _speechSynthesizer = new SpeechSynthesizer();
31 Active = true;
32 Client.Self.OnChat += new MainAvatar.ChatCallback(Self_OnChat);
33 return "TTS is now on.";
34 }
35 else
36 {
37 Active = false;
38 Client.Self.OnChat -= new MainAvatar.ChatCallback(Self_OnChat);
39 return "TTS is now off.";
40 }
41 }
42
43 void Self_OnChat(string message, byte audible, byte type, byte sourcetype, string fromName, LLUUID id, LLUUID ownerid, LLVector3 position)
44 {
45 if (message.Length > 0)
46 {
47 _speechSynthesizer.SpeakAsync(message);
48 }
49 }
50 }
51} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Communication/WhisperCommand.cs b/tools/mass test client/Commands/Communication/WhisperCommand.cs
new file mode 100644
index 0000000..4bfda33
--- /dev/null
+++ b/tools/mass test client/Commands/Communication/WhisperCommand.cs
@@ -0,0 +1,49 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class WhisperCommand : Command
10 {
11 public WhisperCommand(TestClient testClient)
12 {
13 Name = "whisper";
14 Description = "Whisper something.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 int channel = 0;
20 int startIndex = 0;
21 string message = String.Empty;
22 if (args.Length < 1)
23 {
24 return "usage: whisper (optional channel) whatever";
25 }
26 else if (args.Length > 1)
27 {
28 try
29 {
30 channel = Convert.ToInt32(args[0]);
31 startIndex = 1;
32 }
33 catch (FormatException)
34 {
35 channel = 0;
36 }
37 }
38
39 for (int i = startIndex; i < args.Length; i++)
40 {
41 message += args[i] + " ";
42 }
43
44 Client.Self.Chat(message, channel, MainAvatar.ChatType.Whisper);
45
46 return "Whispered " + message;
47 }
48 }
49}
diff --git a/tools/mass test client/Commands/GoHome.cs b/tools/mass test client/Commands/GoHome.cs
new file mode 100644
index 0000000..0ac04f4
--- /dev/null
+++ b/tools/mass test client/Commands/GoHome.cs
@@ -0,0 +1,26 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class GoHomeCommand : Command
10 {
11 public GoHomeCommand(TestClient testClient)
12 {
13 Name = "gohome";
14 Description = "Teleports home";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if ( Client.Self.GoHome() ) {
20 return "Teleport Home Succesful";
21 } else {
22 return "Teleport Home Failed";
23 }
24 }
25 }
26}
diff --git a/tools/mass test client/Commands/GotoLandmark.cs b/tools/mass test client/Commands/GotoLandmark.cs
new file mode 100644
index 0000000..d32047c
--- /dev/null
+++ b/tools/mass test client/Commands/GotoLandmark.cs
@@ -0,0 +1,32 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class GotoLandmarkCommand : Command
10 {
11 public GotoLandmarkCommand(TestClient testClient)
12 {
13 Name = "goto_landmark";
14 Description = "Teleports to a Landmark ";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 LLUUID landmark = new LLUUID();
20 if ( ! LLUUID.TryParse(args[0], out landmark) ) {
21 return "Invalid LLUID";
22 } else {
23 Console.WriteLine("Teleporting to " + landmark.ToString());
24 }
25 if ( Client.Self.Teleport(landmark) ) {
26 return "Teleport Succesful";
27 } else {
28 return "Teleport Failed";
29 }
30 }
31 }
32}
diff --git a/tools/mass test client/Commands/Inventory/AppearanceCommand.cs b/tools/mass test client/Commands/Inventory/AppearanceCommand.cs
new file mode 100644
index 0000000..43aa784
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/AppearanceCommand.cs
@@ -0,0 +1,29 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class AppearanceCommand : Command
10 {
11 Utilities.Assets.AssetManager Assets;
12 Utilities.Appearance.AppearanceManager Appearance;
13
14 public AppearanceCommand(TestClient testClient)
15 {
16 Name = "appearance";
17 Description = "Set your current appearance to your last saved appearance";
18
19 Assets = new libsecondlife.Utilities.Assets.AssetManager(testClient);
20 Appearance = new libsecondlife.Utilities.Appearance.AppearanceManager(testClient, Assets);
21 }
22
23 public override string Execute(string[] args, LLUUID fromAgentID)
24 {
25 Appearance.SetPreviousAppearance();
26 return "Done.";
27 }
28 }
29}
diff --git a/tools/mass test client/Commands/Inventory/BalanceCommand.cs b/tools/mass test client/Commands/Inventory/BalanceCommand.cs
new file mode 100644
index 0000000..46044f2
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/BalanceCommand.cs
@@ -0,0 +1,21 @@
1using System;
2using System.Collections.Generic;
3using libsecondlife;
4using libsecondlife.Packets;
5
6namespace libsecondlife.TestClient
7{
8 public class BalanceCommand: Command
9 {
10 public BalanceCommand(TestClient testClient)
11 {
12 Name = "balance";
13 Description = "Shows the amount of L$.";
14 }
15
16 public override string Execute(string[] args, LLUUID fromAgentID)
17 {
18 return Client.ToString() + " has L$: " + Client.Self.Balance;
19 }
20 }
21}
diff --git a/tools/mass test client/Commands/Inventory/DeleteFolderCommand.cs b/tools/mass test client/Commands/Inventory/DeleteFolderCommand.cs
new file mode 100644
index 0000000..081ff86
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/DeleteFolderCommand.cs
@@ -0,0 +1,43 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using System.Threading;
6using System.Xml;
7using System.Xml.Serialization;
8
9using libsecondlife;
10using libsecondlife.Packets;
11using libsecondlife.InventorySystem;
12
13namespace libsecondlife.TestClient
14{
15 public class DeleteFolderCommand : Command
16 {
17 public DeleteFolderCommand(TestClient testClient)
18 {
19 Name = "deleteFolder";
20 Description = "Deletes a folder from inventory.";
21 }
22
23 public override string Execute(string[] args, LLUUID fromAgentID)
24 {
25 return "Broken until someone fixes me";
26
27 //string target = String.Empty;
28 //for (int ct = 0; ct < args.Length; ct++)
29 // target = target + args[ct] + " ";
30 //target = target.TrimEnd();
31
32 //Client.Inventory.DownloadInventory();
33 //InventoryFolder folder = Client.Inventory.getFolder(target);
34 //if (folder != null)
35 //{
36 // folder.Delete();
37 // return "Folder " + target + " deleted.";
38 //}
39
40 //return "Unable to find: " + target;
41 }
42 }
43} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Inventory/DumpOutfitCommand.cs b/tools/mass test client/Commands/Inventory/DumpOutfitCommand.cs
new file mode 100644
index 0000000..8347acc
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/DumpOutfitCommand.cs
@@ -0,0 +1,98 @@
1using System;
2using System.Text;
3using System.IO;
4using System.Collections.Generic;
5using libsecondlife;
6using libsecondlife.Utilities.Assets;
7using libsecondlife.Utilities.Appearance;
8
9namespace libsecondlife.TestClient
10{
11 public class DumpOutfitCommand : Command
12 {
13 libsecondlife.Utilities.Assets.AssetManager Assets;
14 List<LLUUID> OutfitAssets = new List<LLUUID>();
15
16 public DumpOutfitCommand(TestClient testClient)
17 {
18 Name = "dumpoutfit";
19 Description = "Dumps all of the textures from an avatars outfit to the hard drive. Usage: dumpoutfit [avatar-uuid]";
20
21 Assets = new AssetManager(testClient);
22 Assets.OnImageReceived += new AssetManager.ImageReceivedCallback(Assets_OnImageReceived);
23 }
24
25 public override string Execute(string[] args, LLUUID fromAgentID)
26 {
27 if (args.Length != 1)
28 return "Usage: dumpoutfit [avatar-uuid]";
29
30 LLUUID target;
31
32 if (!LLUUID.TryParse(args[0], out target))
33 return "Usage: dumpoutfit [avatar-uuid]";
34
35 lock (Client.AvatarList)
36 {
37 foreach (Avatar avatar in Client.AvatarList.Values)
38 {
39 if (avatar.ID == target)
40 {
41 StringBuilder output = new StringBuilder("Downloading ");
42
43 lock (OutfitAssets) OutfitAssets.Clear();
44
45 foreach (KeyValuePair<uint, LLObject.TextureEntryFace> face in avatar.Textures.FaceTextures)
46 {
47 ImageType type = ImageType.Normal;
48
49 switch ((AppearanceManager.TextureIndex)face.Key)
50 {
51 case AppearanceManager.TextureIndex.HeadBaked:
52 case AppearanceManager.TextureIndex.EyesBaked:
53 case AppearanceManager.TextureIndex.UpperBaked:
54 case AppearanceManager.TextureIndex.LowerBaked:
55 case AppearanceManager.TextureIndex.SkirtBaked:
56 type = ImageType.Baked;
57 break;
58 }
59
60 Assets.RequestImage(face.Value.TextureID, type, 100000.0f, 0);
61
62 output.Append(((AppearanceManager.TextureIndex)face.Key).ToString());
63 output.Append(" ");
64 }
65
66 return output.ToString();
67 }
68 }
69 }
70
71 return "Couldn't find avatar " + target.ToStringHyphenated();
72 }
73
74 private void Assets_OnImageReceived(ImageDownload image)
75 {
76 if (image.Success)
77 {
78 try
79 {
80 File.WriteAllBytes(image.ID.ToStringHyphenated() + ".jp2", image.AssetData);
81 Console.WriteLine("Wrote JPEG2000 image " + image.ID.ToStringHyphenated() + ".jp2");
82
83 byte[] tgaFile = OpenJPEGNet.OpenJPEG.DecodeToTGA(image.AssetData);
84 File.WriteAllBytes(image.ID.ToStringHyphenated() + ".tga", tgaFile);
85 Console.WriteLine("Wrote TGA image " + image.ID.ToStringHyphenated() + ".tga");
86 }
87 catch (Exception e)
88 {
89 Console.WriteLine(e.ToString());
90 }
91 }
92 else
93 {
94 Console.WriteLine("Failed to download image " + image.ID.ToStringHyphenated());
95 }
96 }
97 }
98}
diff --git a/tools/mass test client/Commands/Inventory/ExportOutfitCommand.cs b/tools/mass test client/Commands/Inventory/ExportOutfitCommand.cs
new file mode 100644
index 0000000..9a91d00
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/ExportOutfitCommand.cs
@@ -0,0 +1,66 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Xml;
5using libsecondlife;
6using libsecondlife.Packets;
7
8namespace libsecondlife.TestClient
9{
10 public class ExportOutfitCommand : Command
11 {
12 public ExportOutfitCommand(TestClient testClient)
13 {
14 Name = "exportoutfit";
15 Description = "Exports an avatars outfit to an xml file. Usage: exportoutfit avataruuid outputfile.xml";
16 }
17
18 public override string Execute(string[] args, LLUUID fromAgentID)
19 {
20 if (args.Length != 2)
21 return "Usage: exportoutfit avataruuid outputfile.xml";
22
23 LLUUID id;
24
25 try
26 {
27 id = new LLUUID(args[0]);
28 }
29 catch (Exception)
30 {
31 return "Usage: exportoutfit avataruuid outputfile.xml";
32 }
33
34 lock (Client.Appearances)
35 {
36 if (Client.Appearances.ContainsKey(id))
37 {
38 try
39 {
40 XmlWriterSettings settings = new XmlWriterSettings();
41 settings.Indent = true;
42 XmlWriter writer = XmlWriter.Create(args[1], settings);
43 try
44 {
45 Client.Appearances[id].ToXml(writer);
46 }
47 finally
48 {
49 writer.Close();
50 }
51 }
52 catch (Exception e)
53 {
54 return e.ToString();
55 }
56
57 return "Exported appearance for avatar " + id.ToString() + " to " + args[1];
58 }
59 else
60 {
61 return "Couldn't find an appearance for avatar " + id.ToString();
62 }
63 }
64 }
65 }
66} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Inventory/GiveAllCommand.cs b/tools/mass test client/Commands/Inventory/GiveAllCommand.cs
new file mode 100644
index 0000000..8890ea0
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/GiveAllCommand.cs
@@ -0,0 +1,27 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class GiveAllCommand: Command
10 {
11 public GiveAllCommand(TestClient testClient)
12 {
13 Name = "giveAll";
14 Description = "Gives you all it's money.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (fromAgentID == null)
20 return "Unable to send money to console. This command only works when IMed.";
21
22 int amount = Client.Self.Balance;
23 Client.Self.GiveMoney(fromAgentID, Client.Self.Balance, String.Empty);
24 return "Gave $" + amount + " to " + fromAgentID;
25 }
26 }
27}
diff --git a/tools/mass test client/Commands/Inventory/ImportOutfitCommand.cs b/tools/mass test client/Commands/Inventory/ImportOutfitCommand.cs
new file mode 100644
index 0000000..595ce98
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/ImportOutfitCommand.cs
@@ -0,0 +1,66 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Xml;
5using System.Xml.Serialization;
6using libsecondlife;
7using libsecondlife.Packets;
8
9namespace libsecondlife.TestClient
10{
11 public class ImportOutfitCommand : Command
12 {
13 private uint SerialNum = 1;
14
15 public ImportOutfitCommand(TestClient testClient)
16 {
17 Name = "importoutfit";
18 Description = "Imports an appearance from an xml file. Usage: importoutfit inputfile.xml";
19 }
20
21 public override string Execute(string[] args, LLUUID fromAgentID)
22 {
23 if (args.Length != 1)
24 return "Usage: importoutfit inputfile.xml";
25
26 try
27 {
28 XmlReader reader = XmlReader.Create(args[0]);
29 XmlSerializer serializer = new XmlSerializer(typeof(Packet));
30 AvatarAppearancePacket appearance = (AvatarAppearancePacket)serializer.Deserialize(reader);
31 reader.Close();
32
33 AgentSetAppearancePacket set = new AgentSetAppearancePacket();
34
35 set.AgentData.AgentID = Client.Network.AgentID;
36 set.AgentData.SessionID = Client.Network.SessionID;
37 set.AgentData.SerialNum = SerialNum++;
38
39 float AV_Height_Range = 2.025506f - 1.50856f;
40 float AV_Height = 1.50856f + (((float)appearance.VisualParam[25].ParamValue / 255.0f) * AV_Height_Range);
41 set.AgentData.Size = new LLVector3(0.45f, 0.6f, AV_Height);
42
43 set.ObjectData.TextureEntry = appearance.ObjectData.TextureEntry;
44 set.VisualParam = new AgentSetAppearancePacket.VisualParamBlock[appearance.VisualParam.Length];
45
46 int i = 0;
47 foreach (AvatarAppearancePacket.VisualParamBlock block in appearance.VisualParam)
48 {
49 set.VisualParam[i] = new AgentSetAppearancePacket.VisualParamBlock();
50 set.VisualParam[i].ParamValue = block.ParamValue;
51 i++;
52 }
53
54 set.WearableData = new AgentSetAppearancePacket.WearableDataBlock[0];
55
56 Client.Network.SendPacket(set);
57 }
58 catch (Exception)
59 {
60 return "Failed to import the appearance XML file, maybe it doesn't exist or is in the wrong format?";
61 }
62
63 return "Imported " + args[0] + " and sent an AgentSetAppearance packet";
64 }
65 }
66}
diff --git a/tools/mass test client/Commands/Inventory/InventoryCommand.cs b/tools/mass test client/Commands/Inventory/InventoryCommand.cs
new file mode 100644
index 0000000..da5dc73
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/InventoryCommand.cs
@@ -0,0 +1,62 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using System.Threading;
6using System.Xml;
7using System.Xml.Serialization;
8
9using libsecondlife;
10using libsecondlife.Packets;
11using libsecondlife.InventorySystem;
12
13namespace libsecondlife.TestClient
14{
15 public class InventoryCommand : Command
16 {
17 public InventoryCommand(TestClient testClient)
18 {
19 Name = "i";
20 Description = "Prints out inventory.";
21 }
22
23 public override string Execute(string[] args, LLUUID fromAgentID)
24 {
25 return "Broken until someone fixes me";
26
27 //Client.Inventory.DownloadInventory();
28 //StringBuilder result = new StringBuilder();
29 //PrintFolder(Client.Inventory.GetRootFolder(), result, 0);
30 //return result.ToString();
31 }
32
33 //void PrintFolder(InventoryFolder folder, StringBuilder output, int indenting)
34 //{
35 // Indent(output, indenting);
36 // output.Append(folder.Name);
37 // output.Append("\n");
38 // foreach (InventoryBase b in folder.GetContents())
39 // {
40 // InventoryItem item = b as InventoryItem;
41 // if (item != null)
42 // {
43 // Indent(output, indenting + 1);
44 // output.Append(item.Name);
45 // output.Append("\n");
46 // continue;
47 // }
48 // InventoryFolder subFolder = b as InventoryFolder;
49 // if (subFolder != null)
50 // PrintFolder(subFolder, output, indenting + 1);
51 // }
52 //}
53
54 //void Indent(StringBuilder output, int indenting)
55 //{
56 // for (int count = 0; count < indenting; count++)
57 // {
58 // output.Append(" ");
59 // }
60 //}
61 }
62} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Inventory/WearCommand.cs b/tools/mass test client/Commands/Inventory/WearCommand.cs
new file mode 100644
index 0000000..d7c1432
--- /dev/null
+++ b/tools/mass test client/Commands/Inventory/WearCommand.cs
@@ -0,0 +1,43 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using System.Threading;
6using System.Xml;
7using System.Xml.Serialization;
8
9using libsecondlife;
10using libsecondlife.Packets;
11using libsecondlife.InventorySystem;
12
13namespace libsecondlife.TestClient
14{
15 public class WearCommand : Command
16 {
17 public WearCommand(TestClient testClient)
18 {
19 Name = "wear";
20 Description = "Wear an outfit folder from inventory. Usage: wear [outfit name]";
21 }
22
23 public override string Execute(string[] args, LLUUID fromAgentID)
24 {
25 string target = String.Empty;
26
27 for (int ct = 0; ct < args.Length; ct++)
28 target = target + args[ct] + " ";
29
30 target = target.TrimEnd();
31
32 InventoryFolder folder = Client.Inventory.getFolder(target);
33
34 if (folder != null)
35 {
36 Client.Appearance.WearOutfit(folder);
37 return "Outfit " + target + " worn.";
38 }
39
40 return "Unable to find: " + target;
41 }
42 }
43}
diff --git a/tools/mass test client/Commands/Land/FindSimCommand.cs b/tools/mass test client/Commands/Land/FindSimCommand.cs
new file mode 100644
index 0000000..4fcd35c
--- /dev/null
+++ b/tools/mass test client/Commands/Land/FindSimCommand.cs
@@ -0,0 +1,43 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class FindSimCommand : Command
10 {
11 public FindSimCommand(TestClient testClient)
12 {
13 Name = "findsim";
14 Description = "Searches for a simulator and returns information about it. Usage: findsim [Simulator Name]";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length < 1)
20 return "Usage: findsim [Simulator Name]";
21
22 // Build the simulator name from the args list
23 string simName = string.Empty;
24 for (int i = 0; i < args.Length; i++)
25 simName += args[i] + " ";
26 simName = simName.TrimEnd().ToLower();
27
28 //if (!GridDataCached[Client])
29 //{
30 // Client.Grid.RequestAllSims(GridManager.MapLayerType.Objects);
31 // System.Threading.Thread.Sleep(5000);
32 // GridDataCached[Client] = true;
33 //}
34
35 GridRegion region;
36
37 if (Client.Grid.GetGridRegion(simName, out region))
38 return String.Format("{0}: handle={1} ({2},{3})", region.Name, region.RegionHandle, region.X, region.Y);
39 else
40 return "Lookup of " + simName + " failed";
41 }
42 }
43}
diff --git a/tools/mass test client/Commands/Land/ParcelInfoCommand.cs b/tools/mass test client/Commands/Land/ParcelInfoCommand.cs
new file mode 100644
index 0000000..7119a47
--- /dev/null
+++ b/tools/mass test client/Commands/Land/ParcelInfoCommand.cs
@@ -0,0 +1,62 @@
1using System;
2using System.Collections.Generic;
3using System.Threading;
4using libsecondlife;
5using libsecondlife.Utilities;
6
7namespace libsecondlife.TestClient
8{
9 public class ParcelInfoCommand : Command
10 {
11 private ParcelDownloader ParcelDownloader;
12 private ManualResetEvent ParcelsDownloaded = new ManualResetEvent(false);
13 private int ParcelCount = 0;
14
15 public ParcelInfoCommand(TestClient testClient)
16 {
17 Name = "parcelinfo";
18 Description = "Prints out info about all the parcels in this simulator";
19
20 ParcelDownloader = new ParcelDownloader(testClient);
21 ParcelDownloader.OnParcelsDownloaded += new ParcelDownloader.ParcelsDownloadedCallback(Parcels_OnParcelsDownloaded);
22 testClient.Network.OnDisconnected += new NetworkManager.DisconnectedCallback(Network_OnDisconnected);
23 }
24
25 public override string Execute(string[] args, LLUUID fromAgentID)
26 {
27 ParcelDownloader.DownloadSimParcels(Client.Network.CurrentSim);
28
29 ParcelsDownloaded.Reset();
30 ParcelsDownloaded.WaitOne(20000, false);
31
32 if (Client.Network.CurrentSim != null)
33 return "Downloaded information for " + ParcelCount + " parcels in " + Client.Network.CurrentSim.Name;
34 else
35 return String.Empty;
36 }
37
38 void Parcels_OnParcelsDownloaded(Simulator simulator, Dictionary<int, Parcel> Parcels, int[,] map)
39 {
40 foreach (KeyValuePair<int, Parcel> parcel in Parcels)
41 {
42 WaterType type = ParcelDownloader.GetWaterType(map, parcel.Value.LocalID);
43 float delta = ParcelDownloader.GetHeightRange(map, parcel.Value.LocalID);
44 int deviation = ParcelDownloader.GetRectangularDeviation(parcel.Value.AABBMin, parcel.Value.AABBMax,
45 parcel.Value.Area);
46
47 Console.WriteLine("Parcels[{0}]: Name: \"{1}\", Description: \"{2}\" ACL Count: {3}, " +
48 "Location: {4}, Height Range: {5}, Shape Deviation: {6}", parcel.Key, parcel.Value.Name,
49 parcel.Value.Desc, parcel.Value.AccessList.Count, type.ToString(), delta, deviation);
50 }
51
52 ParcelCount = Parcels.Count;
53
54 ParcelsDownloaded.Set();
55 }
56
57 void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message)
58 {
59 ParcelsDownloaded.Set();
60 }
61 }
62}
diff --git a/tools/mass test client/Commands/Movement/FollowCommand.cs b/tools/mass test client/Commands/Movement/FollowCommand.cs
new file mode 100644
index 0000000..49be106
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/FollowCommand.cs
@@ -0,0 +1,90 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class FollowCommand: Command
10 {
11 public FollowCommand(TestClient testClient)
12 {
13 Name = "follow";
14 Description = "Follow another avatar. (usage: follow [FirstName LastName]) If no target is set then will follow master.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 string target = String.Empty;
20 for (int ct = 0; ct < args.Length; ct++)
21 target = target + args[ct] + " ";
22 target = target.TrimEnd();
23
24 if (target.Length > 0)
25 {
26 if (Follow(target))
27 return "Following " + target;
28 else
29 return "Unable to follow " + target + ". Client may not be able to see that avatar.";
30 }
31 else
32 {
33 if (Follow(Client.MasterKey))
34 return "Following " + Client.MasterKey;
35 else
36 return "No target specified and no master not found. usage: follow [FirstName LastName])";
37 }
38 }
39
40 const float DISTANCE_BUFFER = 3.0f;
41 Avatar followAvatar;
42
43 bool Follow(string name)
44 {
45 foreach (Avatar av in Client.AvatarList.Values)
46 {
47 if (av.Name == name)
48 {
49 followAvatar = av;
50 Active = true;
51 return true;
52 }
53 }
54 return false;
55 }
56
57 bool Follow(LLUUID id)
58 {
59 foreach (Avatar av in Client.AvatarList.Values)
60 {
61 if (av.ID == id)
62 {
63 followAvatar = av;
64 Active = true;
65 return true;
66 }
67 }
68 return false;
69 }
70
71 public override void Think()
72 {
73 if (Helpers.VecDist(followAvatar.Position, Client.Self.Position) > DISTANCE_BUFFER)
74 {
75 //move toward target
76 LLVector3 avPos = followAvatar.Position;
77 Client.Self.AutoPilot((ulong)avPos.X + (ulong)Client.regionX, (ulong)avPos.Y + (ulong)Client.regionY, avPos.Z);
78 }
79 //else
80 //{
81 // //stop at current position
82 // LLVector3 myPos = client.Self.Position;
83 // client.Self.AutoPilot((ulong)myPos.x, (ulong)myPos.y, myPos.Z);
84 //}
85
86 base.Think();
87 }
88
89 }
90}
diff --git a/tools/mass test client/Commands/Movement/GotoCommand.cs b/tools/mass test client/Commands/Movement/GotoCommand.cs
new file mode 100644
index 0000000..fbbc2ec
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/GotoCommand.cs
@@ -0,0 +1,53 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class GotoCommand: Command
10 {
11 public GotoCommand(TestClient testClient)
12 {
13 Name = "goto";
14 Description = "Teleport to a location (e.g. \"goto Hooper/100/100/30\")";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length < 1)
20 return "usage: Destination should be specified as sim/x/y/z";
21
22 string destination = String.Empty;
23
24 // Handle multi-word sim names by combining the arguments
25 foreach (string arg in args)
26 {
27 destination += arg + " ";
28 }
29 destination = destination.Trim();
30
31 string[] tokens = destination.Split(new char[] { '/' });
32 if (tokens.Length != 4)
33 return "usage: Destination should be specified as sim/x/y/z";
34
35 string sim = tokens[0];
36 float x = Client.Self.Position.X;
37 float y = Client.Self.Position.Y;
38 float z = Client.Self.Position.Z;
39 float.TryParse(tokens[1], out x);
40 float.TryParse(tokens[2], out y);
41 float.TryParse(tokens[3], out z);
42
43 if (Client.Self.Teleport(sim, new LLVector3(x, y, z)))
44 {
45 return "Teleported to " + Client.Network.CurrentSim;
46 }
47 else
48 {
49 return "Teleport failed: " + Client.Self.TeleportMessage;
50 }
51 }
52 }
53}
diff --git a/tools/mass test client/Commands/Movement/JumpCommand.cs b/tools/mass test client/Commands/Movement/JumpCommand.cs
new file mode 100644
index 0000000..6cead83
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/JumpCommand.cs
@@ -0,0 +1,34 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class JumpCommand: Command
10 {
11 public JumpCommand(TestClient testClient)
12 {
13 Name = "jump";
14 Description = "Teleports to the specified height. (e.g. \"jump 1000\")";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length != 1)
20 return "usage: jump 1000";
21
22 float height = 0;
23 float.TryParse(args[0], out height);
24
25 Client.Self.Teleport
26 (
27 Client.Network.CurrentSim.Name,
28 new LLVector3(Client.Self.Position.X, Client.Self.Position.Y, Client.Self.Position.Z + height)
29 );
30
31 return "Jumped " + height;
32 }
33 }
34}
diff --git a/tools/mass test client/Commands/Movement/LocationCommand.cs b/tools/mass test client/Commands/Movement/LocationCommand.cs
new file mode 100644
index 0000000..1758a48
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/LocationCommand.cs
@@ -0,0 +1,23 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class LocationCommand: Command
10 {
11 public LocationCommand(TestClient testClient)
12 {
13 Name = "location";
14 Description = "Show the location.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 return "CurrentSim: '" + Client.Network.CurrentSim.ToString() + "' Position: " +
20 Client.Self.Position.ToString();
21 }
22 }
23}
diff --git a/tools/mass test client/Commands/Movement/MoveToCommand.cs b/tools/mass test client/Commands/Movement/MoveToCommand.cs
new file mode 100644
index 0000000..2b3c7d7
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/MoveToCommand.cs
@@ -0,0 +1,24 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace libsecondlife.TestClient.Commands.Movement {
6 class MovetoCommand : Command {
7 public MovetoCommand(TestClient client) {
8 Name = "moveto";
9 Description = "Moves the avatar to the specified global position using simulator autopilot.";
10 }
11 public override string Execute(string[] args, LLUUID fromAgentID) {
12 if (args.Length != 3)
13 return "usage: moveto x y z";
14 float x = Client.Self.Position.X + Client.regionX;
15 float y = Client.Self.Position.Y + Client.regionY;
16 float z = Client.Self.Position.Z;
17 float.TryParse(args[0], out x);
18 float.TryParse(args[1], out y);
19 float.TryParse(args[2], out z);
20 Client.Self.AutoPilot((ulong)x, (ulong)y, z);
21 return "Attempting to move to <" + x + ", " + y + ", " + z + ">";
22 }
23 }
24}
diff --git a/tools/mass test client/Commands/Movement/SetHome.cs b/tools/mass test client/Commands/Movement/SetHome.cs
new file mode 100644
index 0000000..5e14ca6
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/SetHome.cs
@@ -0,0 +1,23 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class SetHomeCommand : Command
10 {
11 public SetHomeCommand(TestClient testClient)
12 {
13 Name = "sethome";
14 Description = "Sets home to the current location.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 Client.Self.SetHome();
20 return "Home Set";
21 }
22 }
23}
diff --git a/tools/mass test client/Commands/Movement/SitCommand.cs b/tools/mass test client/Commands/Movement/SitCommand.cs
new file mode 100644
index 0000000..1735615
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/SitCommand.cs
@@ -0,0 +1,52 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class SitCommand: Command
10 {
11 public SitCommand(TestClient testClient)
12 {
13 Name = "sit";
14 Description = "Attempt to sit on the closest prim";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 Primitive closest = null;
20 double closestDistance = Double.MaxValue;
21
22 lock (Client.SimPrims)
23 {
24 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
25 {
26 foreach (Primitive p in Client.SimPrims[Client.Network.CurrentSim].Values)
27 {
28 float distance = Helpers.VecDist(Client.Self.Position, p.Position);
29
30 if (closest == null || distance < closestDistance)
31 {
32 closest = p;
33 closestDistance = distance;
34 }
35 }
36 }
37 }
38
39 if (closest != null)
40 {
41 Client.Self.RequestSit(closest.ID, LLVector3.Zero);
42 Client.Self.Sit();
43
44 return "Sat on " + closest.ID + ". Distance: " + closestDistance;
45 }
46 else
47 {
48 return "Couldn't find a nearby prim to sit on";
49 }
50 }
51 }
52}
diff --git a/tools/mass test client/Commands/Movement/SitOnCommand.cs b/tools/mass test client/Commands/Movement/SitOnCommand.cs
new file mode 100644
index 0000000..381f50c
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/SitOnCommand.cs
@@ -0,0 +1,54 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class SitOnCommand: Command
10 {
11 public SitOnCommand(TestClient testClient)
12 {
13 Name = "siton";
14 Description = "Attempt to sit on a particular prim, with specified UUID";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 LLObject targetSeat = null;
20
21 lock (Client.SimPrims)
22 {
23 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
24 {
25 foreach (LLObject p in Client.SimPrims[Client.Network.CurrentSim].Values)
26 {
27 try
28 {
29 if (p.ID == args[0])
30 targetSeat = p;
31 }
32 catch
33 {
34 // handle exception
35 return "Sorry, I don't think " + args[0] + " is a valid UUID. I'm unable to sit there.";
36 }
37 }
38 }
39 }
40
41 if (targetSeat != null)
42 {
43 Client.Self.RequestSit(targetSeat.ID, LLVector3.Zero);
44 Client.Self.Sit();
45
46 return "Sat on prim " + targetSeat.ID + ".";
47 }
48 else
49 {
50 return "Couldn't find specified prim to sit on";
51 }
52 }
53 }
54} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Movement/StandCommand.cs b/tools/mass test client/Commands/Movement/StandCommand.cs
new file mode 100644
index 0000000..bb8542b
--- /dev/null
+++ b/tools/mass test client/Commands/Movement/StandCommand.cs
@@ -0,0 +1,47 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class StandCommand: Command
10 {
11 public StandCommand(TestClient testClient)
12 {
13 Name = "stand";
14 Description = "Stand";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 Client.Self.Status.StandUp = true;
20 stand(Client);
21 return "Standing up.";
22 }
23
24 void stand(SecondLife client)
25 {
26 SendAgentUpdate(client, (uint)MainAvatar.ControlFlags.AGENT_CONTROL_STAND_UP);
27 }
28
29 const float DRAW_DISTANCE = 96.0f;
30 void SendAgentUpdate(SecondLife client, uint ControlID)
31 {
32 AgentUpdatePacket p = new AgentUpdatePacket();
33 p.AgentData.Far = DRAW_DISTANCE;
34 //LLVector3 myPos = client.Self.Position;
35 p.AgentData.CameraCenter = new LLVector3(0, 0, 0);
36 p.AgentData.CameraAtAxis = new LLVector3(0, 0, 0);
37 p.AgentData.CameraLeftAxis = new LLVector3(0, 0, 0);
38 p.AgentData.CameraUpAxis = new LLVector3(0, 0, 0);
39 p.AgentData.HeadRotation = new LLQuaternion(0, 0, 0, 1); ;
40 p.AgentData.BodyRotation = new LLQuaternion(0, 0, 0, 1); ;
41 p.AgentData.AgentID = client.Network.AgentID;
42 p.AgentData.SessionID = client.Network.SessionID;
43 p.AgentData.ControlFlags = ControlID;
44 client.Network.SendPacket(p);
45 }
46 }
47}
diff --git a/tools/mass test client/Commands/Prims/ExportCommand.cs b/tools/mass test client/Commands/Prims/ExportCommand.cs
new file mode 100644
index 0000000..da4e45f
--- /dev/null
+++ b/tools/mass test client/Commands/Prims/ExportCommand.cs
@@ -0,0 +1,209 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Xml;
5using System.Text;
6using System.Threading;
7using libsecondlife;
8using libsecondlife.Packets;
9
10namespace libsecondlife.TestClient
11{
12 public class ExportCommand : Command
13 {
14 AutoResetEvent GotPermissionsEvent = new AutoResetEvent(false);
15 LLObject.ObjectPropertiesFamily Properties;
16 bool GotPermissions = false;
17 LLUUID SelectedObject = LLUUID.Zero;
18
19 Dictionary<LLUUID, Primitive> PrimsWaiting = new Dictionary<LLUUID, Primitive>();
20 AutoResetEvent AllPropertiesReceived = new AutoResetEvent(false);
21
22 public ExportCommand(TestClient testClient)
23 {
24 testClient.Objects.OnObjectPropertiesFamily += new ObjectManager.ObjectPropertiesFamilyCallback(Objects_OnObjectPropertiesFamily);
25 testClient.Objects.OnObjectProperties += new ObjectManager.ObjectPropertiesCallback(Objects_OnObjectProperties);
26 testClient.Avatars.OnPointAt += new AvatarManager.PointAtCallback(Avatars_OnPointAt);
27
28 Name = "export";
29 Description = "Exports an object to an xml file. Usage: export uuid outputfile.xml";
30 }
31
32 public override string Execute(string[] args, LLUUID fromAgentID)
33 {
34 if (args.Length != 2 && !(args.Length == 1 && SelectedObject != LLUUID.Zero))
35 return "Usage: export uuid outputfile.xml";
36
37 LLUUID id;
38 uint localid = 0;
39 int count = 0;
40 string file;
41
42 if (args.Length == 2)
43 {
44 file = args[1];
45 if (!LLUUID.TryParse(args[0], out id))
46 return "Usage: export uuid outputfile.xml";
47 }
48 else
49 {
50 file = args[0];
51 id = SelectedObject;
52 }
53
54 lock (Client.SimPrims)
55 {
56 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
57 {
58 foreach (Primitive prim in Client.SimPrims[Client.Network.CurrentSim].Values)
59 {
60 if (prim.ID == id)
61 {
62 if (prim.ParentID != 0)
63 localid = prim.ParentID;
64 else
65 localid = prim.LocalID;
66
67 break;
68 }
69 }
70 }
71 }
72
73 if (localid != 0)
74 {
75 // Check for export permission first
76 Client.Objects.RequestObjectPropertiesFamily(Client.Network.CurrentSim, id);
77 GotPermissionsEvent.WaitOne(8000, false);
78
79 if (!GotPermissions)
80 {
81 return "Couldn't fetch permissions for the requested object, try again";
82 }
83 else
84 {
85 GotPermissions = false;
86 if (Properties.OwnerID != Client.Network.AgentID &&
87 Properties.OwnerID != Client.MasterKey &&
88 Client.Network.AgentID != Client.Self.ID)
89 {
90 return "That object is owned by " + Properties.OwnerID + ", we don't have permission " +
91 "to export it";
92 }
93 }
94
95 try
96 {
97 XmlWriterSettings settings = new XmlWriterSettings();
98 settings.Indent = true;
99 XmlWriter writer = XmlWriter.Create(file, settings);
100
101 try
102 {
103 List<Primitive> prims = new List<Primitive>();
104
105 lock (Client.SimPrims)
106 {
107 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
108 {
109 foreach (Primitive prim in Client.SimPrims[Client.Network.CurrentSim].Values)
110 {
111 if (prim.LocalID == localid || prim.ParentID == localid)
112 {
113 prims.Add(prim);
114 count++;
115 }
116 }
117 }
118 }
119
120 bool complete = RequestObjectProperties(prims, 250);
121
122 //Serialize it!
123 Helpers.PrimListToXml(prims, writer);
124
125 if (!complete) {
126 Console.WriteLine("Warning: Unable to retrieve full properties for:");
127 foreach (LLUUID uuid in PrimsWaiting.Keys)
128 Console.WriteLine(uuid);
129 }
130 }
131 finally
132 {
133 writer.Close();
134 }
135 }
136 catch (Exception e)
137 {
138 string ret = "Failed to write to " + file + ":" + e.ToString();
139 if (ret.Length > 1000)
140 {
141 ret = ret.Remove(1000);
142 }
143 return ret;
144 }
145 return "Exported " + count + " prims to " + file;
146 }
147 else
148 {
149 return "Couldn't find UUID " + id.ToString() + " in the " +
150 Client.SimPrims[Client.Network.CurrentSim].Count +
151 "objects currently indexed in the current simulator";
152 }
153 }
154
155 private bool RequestObjectProperties(List<Primitive> objects, int msPerRequest)
156 {
157 // Create an array of the local IDs of all the prims we are requesting properties for
158 uint[] localids = new uint[objects.Count];
159
160 lock (PrimsWaiting)
161 {
162 PrimsWaiting.Clear();
163
164 for (int i = 0; i < objects.Count; ++i)
165 {
166 localids[i] = objects[i].LocalID;
167 PrimsWaiting.Add(objects[i].ID, objects[i]);
168 }
169 }
170
171 Client.Objects.SelectObjects(Client.Network.CurrentSim, localids);
172
173 return AllPropertiesReceived.WaitOne(2000 + msPerRequest * objects.Count, false);
174 }
175
176 void Avatars_OnPointAt(LLUUID sourceID, LLUUID targetID, LLVector3d targetPos,
177 MainAvatar.PointAtType pointType, float duration, LLUUID id)
178 {
179 if (sourceID == Client.MasterKey)
180 {
181 //Client.DebugLog("Master is now selecting " + targetID.ToStringHyphenated());
182 SelectedObject = targetID;
183 }
184 }
185
186 void Objects_OnObjectPropertiesFamily(Simulator simulator, LLObject.ObjectPropertiesFamily properties)
187 {
188 Properties = properties;
189 GotPermissions = true;
190 GotPermissionsEvent.Set();
191 }
192
193 void Objects_OnObjectProperties(Simulator simulator, LLObject.ObjectProperties properties)
194 {
195 lock (PrimsWaiting)
196 {
197 Primitive prim;
198 if (PrimsWaiting.TryGetValue(properties.ObjectID, out prim))
199 {
200 prim.Properties = properties;
201 }
202 PrimsWaiting.Remove(properties.ObjectID);
203
204 if (PrimsWaiting.Count == 0)
205 AllPropertiesReceived.Set();
206 }
207 }
208 }
209}
diff --git a/tools/mass test client/Commands/Prims/ExportParticlesCommand.cs b/tools/mass test client/Commands/Prims/ExportParticlesCommand.cs
new file mode 100644
index 0000000..8fced68
--- /dev/null
+++ b/tools/mass test client/Commands/Prims/ExportParticlesCommand.cs
@@ -0,0 +1,119 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Text;
5using libsecondlife;
6
7namespace libsecondlife.TestClient
8{
9 public class ExportParticlesCommand : Command
10 {
11 public ExportParticlesCommand(TestClient testClient)
12 {
13 Name = "exportparticles";
14 Description = "Reverse engineers a prim with a particle system to an LSL script. Usage: exportscript [prim-uuid]";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length != 1)
20 return "Usage: exportparticles [prim-uuid]";
21
22 LLUUID id;
23 if (!LLUUID.TryParse(args[0], out id))
24 return "Usage: exportparticles [prim-uuid]";
25
26 lock (Client.SimPrims)
27 {
28 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
29 {
30 foreach (Primitive prim in Client.SimPrims[Client.Network.CurrentSim].Values)
31 {
32 if (prim.ID == id)
33 {
34 if (prim.ParticleSys.CRC != 0)
35 {
36 StringBuilder lsl = new StringBuilder();
37
38 lsl.Append("default" + Environment.NewLine);
39 lsl.Append("{" + Environment.NewLine);
40 lsl.Append(" state_entry()" + Environment.NewLine);
41 lsl.Append(" {" + Environment.NewLine);
42 lsl.Append(" llParticleSystem([" + Environment.NewLine);
43
44 lsl.Append(" PSYS_PART_FLAGS, 0");
45
46 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpColor) != 0)
47 lsl.Append(" | PSYS_PART_INTERP_COLOR_MASK");
48 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.InterpScale) != 0)
49 lsl.Append(" | PSYS_PART_INTERP_SCALE_MASK");
50 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Bounce) != 0)
51 lsl.Append(" | PSYS_PART_BOUNCE_MASK");
52 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Wind) != 0)
53 lsl.Append(" | PSYS_PART_WIND_MASK");
54 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowSrc) != 0)
55 lsl.Append(" | PSYS_PART_FOLLOW_SRC_MASK");
56 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.FollowVelocity) != 0)
57 lsl.Append(" | PSYS_PART_FOLLOW_VELOCITY_MASK");
58 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetPos) != 0)
59 lsl.Append(" | PSYS_PART_TARGET_POS_MASK");
60 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.TargetLinear) != 0)
61 lsl.Append(" | PSYS_PART_TARGET_LINEAR_MASK");
62 if ((prim.ParticleSys.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.Emissive) != 0)
63 lsl.Append(" | PSYS_PART_EMISSIVE_MASK");
64
65 lsl.Append(","); lsl.Append(Environment.NewLine);
66 lsl.Append(" PSYS_SRC_PATTERN, 0");
67
68 if ((prim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Drop) != 0)
69 lsl.Append(" | PSYS_SRC_PATTERN_DROP");
70 if ((prim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Explode) != 0)
71 lsl.Append(" | PSYS_SRC_PATTERN_EXPLODE");
72 if ((prim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.Angle) != 0)
73 lsl.Append(" | PSYS_SRC_PATTERN_ANGLE");
74 if ((prim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleCone) != 0)
75 lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE");
76 if ((prim.ParticleSys.Pattern & Primitive.ParticleSystem.SourcePattern.AngleConeEmpty) != 0)
77 lsl.Append(" | PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY");
78
79 lsl.Append("," + Environment.NewLine);
80
81 lsl.Append(" PSYS_PART_START_ALPHA, " + String.Format("{0:0.00000}", prim.ParticleSys.PartStartColor.A) + "," + Environment.NewLine);
82 lsl.Append(" PSYS_PART_END_ALPHA, " + String.Format("{0:0.00000}", prim.ParticleSys.PartEndColor.A) + "," + Environment.NewLine);
83 lsl.Append(" PSYS_PART_START_COLOR, " + prim.ParticleSys.PartStartColor.ToStringRGB() + "," + Environment.NewLine);
84 lsl.Append(" PSYS_PART_END_COLOR, " + prim.ParticleSys.PartEndColor.ToStringRGB() + "," + Environment.NewLine);
85 lsl.Append(" PSYS_PART_START_SCALE, <" + String.Format("{0:0.00000}", prim.ParticleSys.PartStartScaleX) + ", " + String.Format("{0:0.00000}", prim.ParticleSys.PartStartScaleY) + ", 0>, " + Environment.NewLine);
86 lsl.Append(" PSYS_PART_END_SCALE, <" + String.Format("{0:0.00000}", prim.ParticleSys.PartEndScaleX) + ", " + String.Format("{0:0.00000}", prim.ParticleSys.PartEndScaleY) + ", 0>, " + Environment.NewLine);
87 lsl.Append(" PSYS_PART_MAX_AGE, " + String.Format("{0:0.00000}", prim.ParticleSys.PartMaxAge) + "," + Environment.NewLine);
88 lsl.Append(" PSYS_SRC_MAX_AGE, " + String.Format("{0:0.00000}", prim.ParticleSys.MaxAge) + "," + Environment.NewLine);
89 lsl.Append(" PSYS_SRC_ACCEL, " + prim.ParticleSys.PartAcceleration.ToString() + "," + Environment.NewLine);
90 lsl.Append(" PSYS_SRC_BURST_PART_COUNT, " + String.Format("{0:0}", prim.ParticleSys.BurstPartCount) + "," + Environment.NewLine);
91 lsl.Append(" PSYS_SRC_BURST_RADIUS, " + String.Format("{0:0.00000}", prim.ParticleSys.BurstRadius) + "," + Environment.NewLine);
92 lsl.Append(" PSYS_SRC_BURST_RATE, " + String.Format("{0:0.00000}", prim.ParticleSys.BurstRate) + "," + Environment.NewLine);
93 lsl.Append(" PSYS_SRC_BURST_SPEED_MIN, " + String.Format("{0:0.00000}", prim.ParticleSys.BurstSpeedMin) + "," + Environment.NewLine);
94 lsl.Append(" PSYS_SRC_BURST_SPEED_MAX, " + String.Format("{0:0.00000}", prim.ParticleSys.BurstSpeedMax) + "," + Environment.NewLine);
95 lsl.Append(" PSYS_SRC_INNERANGLE, " + String.Format("{0:0.00000}", prim.ParticleSys.InnerAngle) + "," + Environment.NewLine);
96 lsl.Append(" PSYS_SRC_OUTERANGLE, " + String.Format("{0:0.00000}", prim.ParticleSys.OuterAngle) + "," + Environment.NewLine);
97 lsl.Append(" PSYS_SRC_OMEGA, " + prim.ParticleSys.AngularVelocity.ToString() + "," + Environment.NewLine);
98 lsl.Append(" PSYS_SRC_TEXTURE, (key)\"" + prim.ParticleSys.Texture.ToStringHyphenated() + "\"," + Environment.NewLine);
99 lsl.Append(" PSYS_SRC_TARGET_KEY, (key)\"" + prim.ParticleSys.Target.ToStringHyphenated() + "\"" + Environment.NewLine);
100
101 lsl.Append(" ]);" + Environment.NewLine);
102 lsl.Append(" }" + Environment.NewLine);
103 lsl.Append("}" + Environment.NewLine);
104
105 return lsl.ToString();
106 }
107 else
108 {
109 return "Prim " + prim.LocalID + " does not have a particle system";
110 }
111 }
112 }
113 }
114 }
115
116 return "Couldn't find prim " + id.ToStringHyphenated();
117 }
118 }
119}
diff --git a/tools/mass test client/Commands/Prims/ImportCommand.cs b/tools/mass test client/Commands/Prims/ImportCommand.cs
new file mode 100644
index 0000000..5f8723a
--- /dev/null
+++ b/tools/mass test client/Commands/Prims/ImportCommand.cs
@@ -0,0 +1,246 @@
1using System;
2using System.Collections.Generic;
3using System.Xml;
4using System.Xml.Serialization;
5using System.Threading;
6using System.IO;
7using libsecondlife;
8
9namespace libsecondlife.TestClient
10{
11 enum ImporterState
12 {
13 RezzingParent,
14 RezzingChildren,
15 Linking,
16 Idle
17 }
18
19 public class Linkset
20 {
21 public Primitive RootPrim;
22 public List<Primitive> Children = new List<Primitive>();
23
24 public Linkset()
25 {
26 RootPrim = new Primitive();
27 }
28
29 public Linkset(Primitive rootPrim)
30 {
31 RootPrim = rootPrim;
32 }
33 }
34
35 public class ImportCommand : Command
36 {
37 Primitive currentPrim;
38 LLVector3 currentPosition;
39 SecondLife currentClient;
40 AutoResetEvent primDone;
41 List<Primitive> primsCreated;
42 List<uint> linkQueue;
43 uint rootLocalID = 0;
44 bool registeredCreateEvent = false;
45
46 ImporterState state = ImporterState.Idle;
47
48 public ImportCommand(TestClient testClient)
49 {
50 Name = "import";
51 Description = "Import prims from an exported xml file. Usage: import inputfile.xml";
52 primDone = new AutoResetEvent(false);
53 registeredCreateEvent = false;
54 }
55
56 public override string Execute(string[] args, LLUUID fromAgentID)
57 {
58 if (args.Length != 1)
59 return "Usage: import inputfile.xml";
60
61 string filename = args[0];
62 Dictionary<uint, Primitive> prims;
63
64 currentClient = Client;
65
66 try
67 {
68 XmlReader reader = XmlReader.Create(filename);
69 List<Primitive> listprims = Helpers.PrimListFromXml(reader);
70 reader.Close();
71
72 // Create a dictionary indexed by the old local ID of the prims
73 prims = new Dictionary<uint, Primitive>();
74 foreach (Primitive prim in listprims)
75 {
76 prims.Add(prim.LocalID, prim);
77 }
78 }
79 catch (Exception)
80 {
81 return "Failed to import the object XML file, maybe it doesn't exist or is in the wrong format?";
82 }
83
84 if (!registeredCreateEvent)
85 {
86 Client.OnPrimCreated += new TestClient.PrimCreatedCallback(TestClient_OnPrimCreated);
87 registeredCreateEvent = true;
88 }
89
90 // Build an organized structure from the imported prims
91 Dictionary<uint, Linkset> linksets = new Dictionary<uint, Linkset>();
92 foreach (Primitive prim in prims.Values)
93 {
94 if (prim.ParentID == 0)
95 {
96 if (linksets.ContainsKey(prim.LocalID))
97 linksets[prim.LocalID].RootPrim = prim;
98 else
99 linksets[prim.LocalID] = new Linkset(prim);
100 }
101 else
102 {
103 if (!linksets.ContainsKey(prim.ParentID))
104 linksets[prim.ParentID] = new Linkset();
105
106 linksets[prim.ParentID].Children.Add(prim);
107 }
108 }
109
110 primsCreated = new List<Primitive>();
111 Console.WriteLine("Importing " + linksets.Count + " structures.");
112
113 foreach (Linkset linkset in linksets.Values)
114 {
115 if (linkset.RootPrim.LocalID != 0)
116 {
117 state = ImporterState.RezzingParent;
118 currentPrim = linkset.RootPrim;
119 // HACK: Offset the root prim position so it's not lying on top of the original
120 // We need a more elaborate solution for importing with relative or absolute offsets
121 linkset.RootPrim.Position = Client.Self.Position;
122 linkset.RootPrim.Position.Z += 3.0f;
123 currentPosition = linkset.RootPrim.Position;
124 // A better solution would move the bot to the desired position.
125 // or to check if we are within a certain distance of the desired position.
126
127 // Rez the root prim with no rotation
128 LLQuaternion rootRotation = linkset.RootPrim.Rotation;
129 linkset.RootPrim.Rotation = LLQuaternion.Identity;
130
131 Client.Objects.AddPrim(Client.Network.CurrentSim, linkset.RootPrim.Data, LLUUID.Zero,
132 linkset.RootPrim.Position, linkset.RootPrim.Scale, linkset.RootPrim.Rotation);
133
134 if (!primDone.WaitOne(10000, false))
135 return "Rez failed, timed out while creating the root prim.";
136
137 state = ImporterState.RezzingChildren;
138
139 // Rez the child prims
140 foreach (Primitive prim in linkset.Children)
141 {
142 currentPrim = prim;
143 currentPosition = prim.Position + linkset.RootPrim.Position;
144
145 Client.Objects.AddPrim(Client.Network.CurrentSim, prim.Data, LLUUID.Zero, currentPosition,
146 prim.Scale, prim.Rotation);
147
148 if (!primDone.WaitOne(10000, false))
149 return "Rez failed, timed out while creating child prim.";
150 }
151
152 if (linkset.Children.Count != 0)
153 {
154 // Create a list of the local IDs of the newly created prims
155 List<uint> primIDs = new List<uint>(primsCreated.Count);
156 primIDs.Add(rootLocalID); // Root prim is first in list.
157 foreach (Primitive prim in primsCreated)
158 {
159 if (prim.LocalID != rootLocalID)
160 primIDs.Add(prim.LocalID);
161 }
162 linkQueue = new List<uint>(primIDs.Count);
163 linkQueue.AddRange(primIDs);
164
165 // Link and set the permissions + rotation
166 state = ImporterState.Linking;
167 Client.Objects.LinkPrims(Client.Network.CurrentSim, linkQueue);
168 if (primDone.WaitOne(100000 * linkset.Children.Count, false))
169 {
170 Client.Objects.SetPermissions(Client.Network.CurrentSim, primIDs,
171 Helpers.PermissionWho.Everyone | Helpers.PermissionWho.Group | Helpers.PermissionWho.NextOwner,
172 Helpers.PermissionType.Copy | Helpers.PermissionType.Modify | Helpers.PermissionType.Move |
173 Helpers.PermissionType.Transfer, true);
174
175 Client.Objects.SetRotation(Client.Network.CurrentSim, rootLocalID, rootRotation);
176 }
177 else
178 {
179 Console.WriteLine("Warning: Failed to link {0} prims", linkQueue.Count);
180 }
181 }
182 else
183 {
184 Client.Objects.SetRotation(Client.Network.CurrentSim, rootLocalID, rootRotation);
185 }
186 state = ImporterState.Idle;
187 }
188 else
189 {
190 // Skip linksets with a missing root prim
191 Console.WriteLine("WARNING: Skipping a linkset with a missing root prim");
192 }
193
194 // Reset everything for the next linkset
195 primsCreated.Clear();
196 }
197
198 return "Import complete.";
199 }
200
201 void TestClient_OnPrimCreated(Simulator simulator, Primitive prim)
202 {
203 if ((prim.Flags & LLObject.ObjectFlags.CreateSelected) == 0)
204 return; // We received an update for an object we didn't create
205
206 switch (state)
207 {
208 case ImporterState.RezzingParent:
209 rootLocalID = prim.LocalID;
210 goto case ImporterState.RezzingChildren;
211 case ImporterState.RezzingChildren:
212 if (!primsCreated.Contains(prim))
213 {
214 Console.WriteLine("Setting properties for " + prim.LocalID);
215 // TODO: Is there a way to set all of this at once, and update more ObjectProperties stuff?
216 currentClient.Objects.SetPosition(simulator, prim.LocalID, currentPosition);
217 currentClient.Objects.SetTextures(simulator, prim.LocalID, currentPrim.Textures);
218 currentClient.Objects.SetLight(simulator, prim.LocalID, currentPrim.Light);
219 currentClient.Objects.SetFlexible(simulator, prim.LocalID, currentPrim.Flexible);
220
221 if (!String.IsNullOrEmpty(currentPrim.Properties.Name))
222 currentClient.Objects.SetName(simulator, prim.LocalID, currentPrim.Properties.Name);
223 if (!String.IsNullOrEmpty(currentPrim.Properties.Description))
224 currentClient.Objects.SetDescription(simulator, prim.LocalID,
225 currentPrim.Properties.Description);
226
227 primsCreated.Add(prim);
228 primDone.Set();
229 }
230 break;
231 case ImporterState.Linking:
232 lock (linkQueue)
233 {
234 int index = linkQueue.IndexOf(prim.LocalID);
235 if (index != -1)
236 {
237 linkQueue.RemoveAt(index);
238 if (linkQueue.Count == 0)
239 primDone.Set();
240 }
241 }
242 break;
243 }
244 }
245 }
246}
diff --git a/tools/mass test client/Commands/Prims/PrimCountCommand.cs b/tools/mass test client/Commands/Prims/PrimCountCommand.cs
new file mode 100644
index 0000000..5d07e8b
--- /dev/null
+++ b/tools/mass test client/Commands/Prims/PrimCountCommand.cs
@@ -0,0 +1,32 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class PrimCountCommand: Command
10 {
11 public PrimCountCommand(TestClient testClient)
12 {
13 Name = "primcount";
14 Description = "Shows the number of prims that have been received.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 int count = 0;
20
21 lock (Client.SimPrims)
22 {
23 foreach (Dictionary<uint, Primitive> prims in Client.SimPrims.Values)
24 {
25 count += prims.Count;
26 }
27 }
28
29 return count.ToString();
30 }
31 }
32}
diff --git a/tools/mass test client/Commands/Stats/DilationCommand.cs b/tools/mass test client/Commands/Stats/DilationCommand.cs
new file mode 100644
index 0000000..e6e0a4d
--- /dev/null
+++ b/tools/mass test client/Commands/Stats/DilationCommand.cs
@@ -0,0 +1,22 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class DilationCommand : Command
10 {
11 public DilationCommand(TestClient testClient)
12 {
13 Name = "dilation";
14 Description = "Shows time dilation for current sim.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 return "Dilation is " + Client.Network.CurrentSim.Dilation.ToString();
20 }
21 }
22} \ No newline at end of file
diff --git a/tools/mass test client/Commands/Stats/RegionInfoCommand.cs b/tools/mass test client/Commands/Stats/RegionInfoCommand.cs
new file mode 100644
index 0000000..750175f
--- /dev/null
+++ b/tools/mass test client/Commands/Stats/RegionInfoCommand.cs
@@ -0,0 +1,45 @@
1using System;
2using System.Text;
3using libsecondlife;
4
5namespace libsecondlife.TestClient
6{
7 public class RegionInfoCommand : Command
8 {
9 public RegionInfoCommand(TestClient testClient)
10 {
11 Name = "regioninfo";
12 Description = "Prints out info about all the current region";
13 }
14
15 public override string Execute(string[] args, LLUUID fromAgentID)
16 {
17 StringBuilder output = new StringBuilder();
18 output.AppendLine(Client.Network.CurrentSim.ToString());
19 output.Append("Access: ");
20 output.AppendLine(Client.Network.CurrentSim.Access.ToString());
21 output.Append("Flags: ");
22 output.AppendLine(Client.Network.CurrentSim.Flags.ToString());
23 output.Append("TerrainBase0: ");
24 output.AppendLine(Client.Network.CurrentSim.TerrainBase0.ToStringHyphenated());
25 output.Append("TerrainBase1: ");
26 output.AppendLine(Client.Network.CurrentSim.TerrainBase1.ToStringHyphenated());
27 output.Append("TerrainBase2: ");
28 output.AppendLine(Client.Network.CurrentSim.TerrainBase2.ToStringHyphenated());
29 output.Append("TerrainBase3: ");
30 output.AppendLine(Client.Network.CurrentSim.TerrainBase3.ToStringHyphenated());
31 output.Append("TerrainDetail0: ");
32 output.AppendLine(Client.Network.CurrentSim.TerrainDetail0.ToStringHyphenated());
33 output.Append("TerrainDetail1: ");
34 output.AppendLine(Client.Network.CurrentSim.TerrainDetail1.ToStringHyphenated());
35 output.Append("TerrainDetail2: ");
36 output.AppendLine(Client.Network.CurrentSim.TerrainDetail2.ToStringHyphenated());
37 output.Append("TerrainDetail3: ");
38 output.AppendLine(Client.Network.CurrentSim.TerrainDetail3.ToStringHyphenated());
39 output.Append("Water Height: ");
40 output.AppendLine(Client.Network.CurrentSim.WaterHeight.ToString());
41
42 return output.ToString();
43 }
44 }
45}
diff --git a/tools/mass test client/Commands/Stats/StatsCommand.cs b/tools/mass test client/Commands/Stats/StatsCommand.cs
new file mode 100644
index 0000000..cf3e4e9
--- /dev/null
+++ b/tools/mass test client/Commands/Stats/StatsCommand.cs
@@ -0,0 +1,44 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class StatsCommand : Command
10 {
11 public StatsCommand(TestClient testClient)
12 {
13 Name = "stats";
14 Description = "Provide connection figures and statistics";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 StringBuilder output = new StringBuilder();
20
21 lock (Client.Network.Simulators)
22 {
23 for (int i = 0; i < Client.Network.Simulators.Count; i++)
24 {
25 Simulator sim = Client.Network.Simulators[i];
26
27 output.AppendLine(String.Format(
28 "[{0}] Dilation: {1} InBPS: {2} OutBPS: {3} ResentOut: {4} ResentIn: {5}",
29 sim.ToString(), sim.Dilation, sim.IncomingBPS, sim.OutgoingBPS, sim.ResentPackets,
30 sim.ReceivedResends));
31 }
32 }
33 output.Append("Packets in the queue: " + Client.Network.InboxCount);
34 output.AppendLine(String.Format("FPS : {0} PhysicsFPS : {1} AgentUpdates : {2} Objects : {3} Scripted Objects : {4}",
35 Client.Network.CurrentSim.FPS, Client.Network.CurrentSim.PhysicsFPS, Client.Network.CurrentSim.AgentUpdates, Client.Network.CurrentSim.Objects, Client.Network.CurrentSim.ScriptedObjects));
36 output.AppendLine(String.Format("Frame Time : {0} Net Time : {1} Image Time : {2} Physics Time : {3} Script Time : {4} Other Time : {5}",
37 Client.Network.CurrentSim.FrameTime, Client.Network.CurrentSim.NetTime, Client.Network.CurrentSim.ImageTime, Client.Network.CurrentSim.PhysicsTime, Client.Network.CurrentSim.ScriptTime, Client.Network.CurrentSim.OtherTime));
38 output.AppendLine(String.Format("Agents : {0} Child Agents : {1} Active Scripts : {2}",
39 Client.Network.CurrentSim.Agents, Client.Network.CurrentSim.ChildAgents, Client.Network.CurrentSim.ActiveScripts));
40
41 return output.ToString();
42 }
43 }
44}
diff --git a/tools/mass test client/Commands/Stats/UptimeCommand.cs b/tools/mass test client/Commands/Stats/UptimeCommand.cs
new file mode 100644
index 0000000..ac94644
--- /dev/null
+++ b/tools/mass test client/Commands/Stats/UptimeCommand.cs
@@ -0,0 +1,25 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class UptimeCommand : Command
10 {
11 public DateTime Created = DateTime.Now;
12
13 public UptimeCommand(TestClient testClient)
14 {
15 Name = "uptime";
16 Description = "Shows the login name, login time and length of time logged on.";
17 }
18
19 public override string Execute(string[] args, LLUUID fromAgentID)
20 {
21 string name = Client.ToString();
22 return "I am " + name + ", Up Since: " + Created + " (" + (DateTime.Now - Created) + ")";
23 }
24 }
25} \ No newline at end of file
diff --git a/tools/mass test client/Commands/System/DebugCommand.cs b/tools/mass test client/Commands/System/DebugCommand.cs
new file mode 100644
index 0000000..07e2a6c
--- /dev/null
+++ b/tools/mass test client/Commands/System/DebugCommand.cs
@@ -0,0 +1,37 @@
1using System;
2using System.Collections.Generic;
3using libsecondlife;
4using libsecondlife.Packets;
5
6namespace libsecondlife.TestClient
7{
8 public class DebugCommand : Command
9 {
10 public DebugCommand(TestClient testClient)
11 {
12 Name = "debug";
13 Description = "Turn debug messages on or off. Usage: debug [on/off]";
14 }
15
16 public override string Execute(string[] args, LLUUID fromAgentID)
17 {
18 if (args.Length != 1)
19 return "Usage: debug [on/off]";
20
21 if (args[0].ToLower() == "on")
22 {
23 Client.Settings.DEBUG = true;
24 return "Debug logging is on";
25 }
26 else if (args[0].ToLower() == "off")
27 {
28 Client.Settings.DEBUG = false;
29 return "Debug logging is off";
30 }
31 else
32 {
33 return "Usage: debug [on/off]";
34 }
35 }
36 }
37}
diff --git a/tools/mass test client/Commands/System/HelpCommand.cs b/tools/mass test client/Commands/System/HelpCommand.cs
new file mode 100644
index 0000000..a53b3c0
--- /dev/null
+++ b/tools/mass test client/Commands/System/HelpCommand.cs
@@ -0,0 +1,29 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class HelpCommand: Command
10 {
11 public HelpCommand(TestClient testClient)
12 {
13 Name = "help";
14 Description = "Lists available commands.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 StringBuilder result = new StringBuilder();
20 result.AppendFormat("\n\nHELP\nClient accept teleport lures from master and group members.\n");
21 foreach (Command c in Client.Commands.Values)
22 {
23 result.AppendFormat(" * {0} - {1}\n", c.Name, c.Description);
24 }
25
26 return result.ToString();
27 }
28 }
29}
diff --git a/tools/mass test client/Commands/System/LoadCommand.cs b/tools/mass test client/Commands/System/LoadCommand.cs
new file mode 100644
index 0000000..24d2219
--- /dev/null
+++ b/tools/mass test client/Commands/System/LoadCommand.cs
@@ -0,0 +1,28 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Reflection;
5using libsecondlife;
6using libsecondlife.Packets;
7
8namespace libsecondlife.TestClient
9{
10 public class LoadCommand: Command
11 {
12 public LoadCommand(TestClient testClient)
13 {
14 Name = "load";
15 Description = "Loads commands from a dll. (Usage: load AssemblyNameWithoutExtension)";
16 }
17
18 public override string Execute(string[] args, LLUUID fromAgentID)
19 {
20 if (args.Length < 1)
21 return "Usage: load AssemblyNameWithoutExtension";
22
23 string filename = AppDomain.CurrentDomain.BaseDirectory + args[0] + ".dll";
24 Client.RegisterAllCommands(Assembly.LoadFile(filename));
25 return "Assembly " + filename + " loaded.";
26 }
27 }
28}
diff --git a/tools/mass test client/Commands/System/LoginCommand.cs b/tools/mass test client/Commands/System/LoginCommand.cs
new file mode 100644
index 0000000..6cfc155
--- /dev/null
+++ b/tools/mass test client/Commands/System/LoginCommand.cs
@@ -0,0 +1,34 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class LoginCommand : Command
10 {
11 public LoginCommand(TestClient testClient)
12 {
13 Name = "login";
14 Description = "Logs in another avatar";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length != 3 && args.Length != 4)
20 return "usage: login firstname lastname password [simname]";
21
22 SecondLife newClient = Client.ClientManager.Login(args);
23
24 if (newClient.Network.Connected)
25 {
26 return "Logged in " + newClient.ToString();
27 }
28 else
29 {
30 return "Failed to login: " + newClient.Network.LoginMessage;
31 }
32 }
33 }
34}
diff --git a/tools/mass test client/Commands/System/LogoutCommand.cs b/tools/mass test client/Commands/System/LogoutCommand.cs
new file mode 100644
index 0000000..8241626
--- /dev/null
+++ b/tools/mass test client/Commands/System/LogoutCommand.cs
@@ -0,0 +1,24 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class LogoutCommand : Command
10 {
11 public LogoutCommand(TestClient testClient)
12 {
13 Name = "logout";
14 Description = "Log this avatar out";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 string name = Client.ToString();
20 Client.ClientManager.Logout(Client);
21 return "Logged " + name + " out";
22 }
23 }
24}
diff --git a/tools/mass test client/Commands/System/MD5Command.cs b/tools/mass test client/Commands/System/MD5Command.cs
new file mode 100644
index 0000000..2084e67
--- /dev/null
+++ b/tools/mass test client/Commands/System/MD5Command.cs
@@ -0,0 +1,22 @@
1using System;
2using libsecondlife;
3
4namespace libsecondlife.TestClient
5{
6 public class MD5Command : Command
7 {
8 public MD5Command(TestClient testClient)
9 {
10 Name = "md5";
11 Description = "Creates an MD5 hash from a given password. Usage: md5 [password]";
12 }
13
14 public override string Execute(string[] args, LLUUID fromAgentID)
15 {
16 if (args.Length == 1)
17 return Helpers.MD5(args[0]);
18 else
19 return "Usage: md5 [password]";
20 }
21 }
22}
diff --git a/tools/mass test client/Commands/System/PacketLogCommand.cs b/tools/mass test client/Commands/System/PacketLogCommand.cs
new file mode 100644
index 0000000..694cee1
--- /dev/null
+++ b/tools/mass test client/Commands/System/PacketLogCommand.cs
@@ -0,0 +1,84 @@
1using System;
2using System.Collections.Generic;
3using System.Xml;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class PacketLogCommand : Command
10 {
11 List<Packet> Packets = new List<Packet>();
12 bool Done = false;
13 int Count = 0;
14 int Total = 0;
15
16 public PacketLogCommand(TestClient testClient)
17 {
18 Name = "packetlog";
19 Description = "Logs a given number of packets to an xml file. Usage: packetlog 10 tenpackets.xml";
20 }
21
22 public override string Execute(string[] args, LLUUID fromAgentID)
23 {
24 if (args.Length != 2)
25 return "Usage: packetlog 10 tenpackets.xml";
26
27 XmlWriter writer;
28 NetworkManager.PacketCallback callback = new NetworkManager.PacketCallback(OnPacket);
29
30 Packets.Clear();
31 Done = false;
32 Count = 0;
33
34 try
35 {
36 Total = Int32.Parse(args[0]);
37 writer = XmlWriter.Create(args[1]);
38
39 Client.Network.RegisterCallback(PacketType.Default, callback);
40 }
41 catch (Exception e)
42 {
43 return "Usage: packetlog 10 tenpackets.xml (" + e + ")";
44 }
45
46 while (!Done)
47 {
48 System.Threading.Thread.Sleep(100);
49 }
50
51 Client.Network.UnregisterCallback(PacketType.Default, callback);
52
53 try
54 {
55 Helpers.PacketListToXml(Packets, writer);
56 }
57 catch (Exception e)
58 {
59 return "Serialization failed: " + e.ToString();
60 }
61
62 writer.Close();
63 Packets.Clear();
64
65 return "Exported " + Count + " packets to " + args[1];
66 }
67
68 private void OnPacket(Packet packet, Simulator simulator)
69 {
70 lock (Packets)
71 {
72 if (Count >= Total)
73 {
74 Done = true;
75 }
76 else
77 {
78 Packets.Add(packet);
79 Count++;
80 }
81 }
82 }
83 }
84}
diff --git a/tools/mass test client/Commands/System/QuitCommand.cs b/tools/mass test client/Commands/System/QuitCommand.cs
new file mode 100644
index 0000000..2cf0418
--- /dev/null
+++ b/tools/mass test client/Commands/System/QuitCommand.cs
@@ -0,0 +1,24 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class QuitCommand: Command
10 {
11 public QuitCommand(TestClient testClient)
12 {
13 Name = "quit";
14 Description = "Log all avatars out and shut down";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 Client.ClientManager.LogoutAll();
20 Client.ClientManager.Running = false;
21 return "All avatars logged out";
22 }
23 }
24}
diff --git a/tools/mass test client/Commands/System/SetMasterCommand.cs b/tools/mass test client/Commands/System/SetMasterCommand.cs
new file mode 100644
index 0000000..8601865
--- /dev/null
+++ b/tools/mass test client/Commands/System/SetMasterCommand.cs
@@ -0,0 +1,73 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5using libsecondlife;
6using libsecondlife.Packets;
7
8namespace libsecondlife.TestClient
9{
10 public class SetMasterCommand: Command
11 {
12 public DateTime Created = DateTime.Now;
13 private LLUUID resolvedMasterKey = LLUUID.Zero;
14 private ManualResetEvent keyResolution = new ManualResetEvent(false);
15 private LLUUID query = LLUUID.Zero;
16
17 public SetMasterCommand(TestClient testClient)
18 {
19 Name = "setMaster";
20 Description = "Sets the user name of the master user. The master user can IM to run commands.";
21
22 }
23
24 public override string Execute(string[] args, LLUUID fromAgentID)
25 {
26 string masterName = String.Empty;
27 for (int ct = 0; ct < args.Length;ct++)
28 masterName = masterName + args[ct] + " ";
29 masterName = masterName.TrimEnd();
30
31 if (masterName.Length == 0)
32 return "Usage setMaster name";
33
34 DirectoryManager.DirPeopleReplyCallback callback = new DirectoryManager.DirPeopleReplyCallback(KeyResolvHandler);
35 Client.Directory.OnDirPeopleReply += callback;
36 query = Client.Directory.StartPeopleSearch(DirectoryManager.DirFindFlags.People, masterName, 0);
37 if (keyResolution.WaitOne(TimeSpan.FromMinutes(1), false))
38 {
39 Client.MasterKey = resolvedMasterKey;
40 keyResolution.Reset();
41 Client.Directory.OnDirPeopleReply -= callback;
42 }
43 else
44 {
45 keyResolution.Reset();
46 Client.Directory.OnDirPeopleReply -= callback;
47 return "Unable to obtain UUID for \"" + masterName + "\". Master unchanged.";
48 }
49
50
51 foreach (Avatar av in Client.AvatarList.Values)
52 {
53 if (av.ID == Client.MasterKey)
54 {
55 Client.Self.InstantMessage(av.ID, "You are now my master. IM me with \"help\" for a command list.");
56 break;
57 }
58 }
59
60 return "Master set to " + masterName + " (" + Client.MasterKey.ToStringHyphenated() + ")";
61 }
62
63 private void KeyResolvHandler(LLUUID queryid, List<DirectoryManager.AgentSearchData> matches)
64 {
65 if (query != queryid)
66 return;
67 // We can't handle ambiguities here as nicely as we can in ClientManager.
68 resolvedMasterKey = matches[0].AgentID;
69 keyResolution.Set();
70 query = LLUUID.Zero;
71 }
72 }
73}
diff --git a/tools/mass test client/Commands/System/SetMasterKeyCommand.cs b/tools/mass test client/Commands/System/SetMasterKeyCommand.cs
new file mode 100644
index 0000000..1fa6336
--- /dev/null
+++ b/tools/mass test client/Commands/System/SetMasterKeyCommand.cs
@@ -0,0 +1,35 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class SetMasterKeyCommand : Command
10 {
11 public DateTime Created = DateTime.Now;
12
13 public SetMasterKeyCommand(TestClient testClient)
14 {
15 Name = "setMasterKey";
16 Description = "Sets the key of the master user. The master user can IM to run commands.";
17 }
18
19 public override string Execute(string[] args, LLUUID fromAgentID)
20 {
21 Client.MasterKey = LLUUID.Parse(args[0]);
22
23 foreach (Avatar av in Client.AvatarList.Values)
24 {
25 if (av.ID == Client.MasterKey)
26 {
27 Client.Self.InstantMessage(av.ID, "You are now my master. IM me with \"help\" for a command list.");
28 break;
29 }
30 }
31
32 return "Master set to " + Client.MasterKey;
33 }
34 }
35}
diff --git a/tools/mass test client/Commands/System/ShowEffectsCommand.cs b/tools/mass test client/Commands/System/ShowEffectsCommand.cs
new file mode 100644
index 0000000..4d46e35
--- /dev/null
+++ b/tools/mass test client/Commands/System/ShowEffectsCommand.cs
@@ -0,0 +1,76 @@
1using System;
2using libsecondlife;
3
4namespace libsecondlife.TestClient
5{
6 public class ShowEffectsCommand : Command
7 {
8 bool ShowEffects = false;
9
10 public ShowEffectsCommand(TestClient testClient)
11 {
12 Name = "showeffects";
13 Description = "Prints out information for every viewer effect that is received. Usage: showeffects [on/off]";
14
15 testClient.Avatars.OnEffect += new AvatarManager.EffectCallback(Avatars_OnEffect);
16 testClient.Avatars.OnLookAt += new AvatarManager.LookAtCallback(Avatars_OnLookAt);
17 testClient.Avatars.OnPointAt += new AvatarManager.PointAtCallback(Avatars_OnPointAt);
18 }
19
20 public override string Execute(string[] args, LLUUID fromAgentID)
21 {
22 if (args.Length == 0)
23 {
24 ShowEffects = true;
25 return "Viewer effects will be shown on the console";
26 }
27 else if (args.Length == 1)
28 {
29 if (args[0] == "on")
30 {
31 ShowEffects = true;
32 return "Viewer effects will be shown on the console";
33 }
34 else
35 {
36 ShowEffects = false;
37 return "Viewer effects will not be shown";
38 }
39 }
40 else
41 {
42 return "Usage: showeffects [on/off]";
43 }
44 }
45
46 private void Avatars_OnPointAt(LLUUID sourceID, LLUUID targetID, LLVector3d targetPos,
47 MainAvatar.PointAtType pointType, float duration, LLUUID id)
48 {
49 if (ShowEffects)
50 Console.WriteLine(
51 "ViewerEffect [PointAt]: SourceID: {0} TargetID: {1} TargetPos: {2} Type: {3} Duration: {4} ID: {5}",
52 sourceID.ToStringHyphenated(), targetID.ToStringHyphenated(), targetPos, pointType, duration,
53 id.ToStringHyphenated());
54 }
55
56 private void Avatars_OnLookAt(LLUUID sourceID, LLUUID targetID, LLVector3d targetPos,
57 MainAvatar.LookAtType lookType, float duration, LLUUID id)
58 {
59 if (ShowEffects)
60 Console.WriteLine(
61 "ViewerEffect [LookAt]: SourceID: {0} TargetID: {1} TargetPos: {2} Type: {3} Duration: {4} ID: {5}",
62 sourceID.ToStringHyphenated(), targetID.ToStringHyphenated(), targetPos, lookType, duration,
63 id.ToStringHyphenated());
64 }
65
66 private void Avatars_OnEffect(MainAvatar.EffectType type, LLUUID sourceID, LLUUID targetID,
67 LLVector3d targetPos, float duration, LLUUID id)
68 {
69 if (ShowEffects)
70 Console.WriteLine(
71 "ViewerEffect [{0}]: SourceID: {1} TargetID: {2} TargetPos: {3} Duration: {4} ID: {5}",
72 type, sourceID.ToStringHyphenated(), targetID.ToStringHyphenated(), targetPos, duration,
73 id.ToStringHyphenated());
74 }
75 }
76}
diff --git a/tools/mass test client/Commands/TouchCommand.cs b/tools/mass test client/Commands/TouchCommand.cs
new file mode 100644
index 0000000..f585b87
--- /dev/null
+++ b/tools/mass test client/Commands/TouchCommand.cs
@@ -0,0 +1,55 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class TouchCommand: Command
10 {
11 public TouchCommand(TestClient testClient)
12 {
13 Name = "touch";
14 Description = "Attempt to touch a prim with specified UUID";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 Primitive target = null;
20
21 lock (Client.SimPrims)
22 {
23 if (Client.SimPrims.ContainsKey(Client.Network.CurrentSim))
24 {
25 foreach (Primitive p in Client.SimPrims[Client.Network.CurrentSim].Values)
26 {
27 if (args.Length == 0)
28 return "You must specify a UUID of the prim.";
29
30 try
31 {
32 if (p.ID == args[0])
33 target = p;
34 }
35 catch
36 {
37 // handle exception
38 return "Sorry, I don't think " + args[0] + " is a valid UUID. I'm unable to touch it.";
39 }
40 }
41 }
42 }
43
44 if (target != null)
45 {
46 Client.Self.Touch(target.LocalID);
47 return "Touched prim " + target.ID + ".";
48 }
49 else
50 {
51 return "Couldn't find that prim.";
52 }
53 }
54 }
55} \ No newline at end of file
diff --git a/tools/mass test client/Commands/TreeCommand.cs b/tools/mass test client/Commands/TreeCommand.cs
new file mode 100644
index 0000000..60cf234
--- /dev/null
+++ b/tools/mass test client/Commands/TreeCommand.cs
@@ -0,0 +1,51 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class TreeCommand: Command
10 {
11 public TreeCommand(TestClient testClient)
12 {
13 Name = "tree";
14 Description = "Rez a tree.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 if (args.Length == 1)
20 {
21 try
22 {
23 string treeName = args[0].Trim(new char[] { ' ' });
24 ObjectManager.Tree tree = (ObjectManager.Tree)Enum.Parse(typeof(ObjectManager.Tree), treeName);
25
26 LLVector3 treePosition = new LLVector3(Client.Self.Position.X, Client.Self.Position.Y,
27 Client.Self.Position.Z);
28 treePosition.Z += 3.0f;
29
30 Client.Objects.AddTree(Client.Network.CurrentSim, new LLVector3(0.5f, 0.5f, 0.5f),
31 LLQuaternion.Identity, treePosition, tree, Client.GroupID, false);
32
33 return "Attempted to rez a " + treeName + " tree";
34 }
35 catch (Exception)
36 {
37 return "Type !tree for usage";
38 }
39 }
40
41 string usage = "Usage: !tree [";
42 foreach (string value in Enum.GetNames(typeof(ObjectManager.Tree)))
43 {
44 usage += value + ",";
45 }
46 usage = usage.TrimEnd(new char[] { ',' });
47 usage += "]";
48 return usage;
49 }
50 }
51}
diff --git a/tools/mass test client/Commands/WhoCommand.cs b/tools/mass test client/Commands/WhoCommand.cs
new file mode 100644
index 0000000..3edb649
--- /dev/null
+++ b/tools/mass test client/Commands/WhoCommand.cs
@@ -0,0 +1,29 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace libsecondlife.TestClient
8{
9 public class WhoCommand: Command
10 {
11 public WhoCommand(TestClient testClient)
12 {
13 Name = "who";
14 Description = "Lists seen avatars.";
15 }
16
17 public override string Execute(string[] args, LLUUID fromAgentID)
18 {
19 StringBuilder result = new StringBuilder();
20 foreach (Avatar av in Client.AvatarList.Values)
21 {
22 result.AppendFormat("\n{0} {1} {2}/{3} ID: {4}", av.Name, av.GroupName,
23 (av.CurrentSim != null ? av.CurrentSim.Name : String.Empty), av.Position, av.ID);
24 }
25
26 return result.ToString();
27 }
28 }
29}
diff --git a/tools/mass test client/MassTestClient.csproj b/tools/mass test client/MassTestClient.csproj
new file mode 100644
index 0000000..0f5b6a6
--- /dev/null
+++ b/tools/mass test client/MassTestClient.csproj
@@ -0,0 +1,121 @@
1<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <PropertyGroup>
3 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <ProductVersion>8.0.50727</ProductVersion>
6 <SchemaVersion>2.0</SchemaVersion>
7 <ProjectGuid>{B87682F6-B2D7-4C4D-A529-400C24FD4880}</ProjectGuid>
8 <OutputType>Exe</OutputType>
9 <AppDesignerFolder>Properties</AppDesignerFolder>
10 <RootNamespace>libsecondlife.MassTestClient</RootNamespace>
11 <AssemblyName>MassTestClient</AssemblyName>
12 </PropertyGroup>
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 <DebugSymbols>true</DebugSymbols>
15 <DebugType>full</DebugType>
16 <Optimize>false</Optimize>
17 <OutputPath>..\..\..\bin\</OutputPath>
18 <DefineConstants>DEBUG;TRACE</DefineConstants>
19 <ErrorReport>prompt</ErrorReport>
20 <WarningLevel>4</WarningLevel>
21 </PropertyGroup>
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <DebugType>pdbonly</DebugType>
24 <Optimize>true</Optimize>
25 <OutputPath>bin\</OutputPath>
26 <DefineConstants>TRACE</DefineConstants>
27 <ErrorReport>prompt</ErrorReport>
28 <WarningLevel>4</WarningLevel>
29 </PropertyGroup>
30 <ItemGroup>
31 <Reference Include="libsecondlife, Version=0.9.0.0, Culture=neutral, processorArchitecture=MSIL">
32 <SpecificVersion>False</SpecificVersion>
33 <HintPath>bin\libsecondlife.dll</HintPath>
34 </Reference>
35 <Reference Include="libsecondlife.Utilities, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
36 <SpecificVersion>False</SpecificVersion>
37 <HintPath>bin\libsecondlife.Utilities.dll</HintPath>
38 </Reference>
39 <Reference Include="openjpegnet, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
40 <SpecificVersion>False</SpecificVersion>
41 <HintPath>bin\openjpegnet.dll</HintPath>
42 </Reference>
43 <Reference Include="System" />
44 <Reference Include="System.Data" />
45 <Reference Include="System.Xml" />
46 </ItemGroup>
47 <ItemGroup>
48 <Compile Include="Arguments.cs" />
49 <Compile Include="Command.cs" />
50 <Compile Include="Commands\Inventory\AppearanceCommand.cs" />
51 <Compile Include="Commands\CloneProfileCommand.cs" />
52 <Compile Include="Commands\System\DebugCommand.cs" />
53 <Compile Include="Commands\Inventory\DumpOutfitCommand.cs" />
54 <Compile Include="Commands\Prims\ExportParticlesCommand.cs" />
55 <Compile Include="Commands\Inventory\BalanceCommand.cs" />
56 <Compile Include="Commands\Inventory\DeleteFolderCommand.cs" />
57 <Compile Include="Commands\Inventory\GiveAllCommand.cs" />
58 <Compile Include="Commands\Inventory\WearCommand.cs" />
59 <Compile Include="Commands\Inventory\InventoryCommand.cs" />
60 <Compile Include="Commands\Inventory\ExportOutfitCommand.cs" />
61 <Compile Include="Commands\Land\FindSimCommand.cs" />
62 <Compile Include="Commands\Inventory\ImportOutfitCommand.cs" />
63 <Compile Include="Commands\System\LoginCommand.cs">
64 <SubType>Code</SubType>
65 </Compile>
66 <Compile Include="Commands\System\LogoutCommand.cs">
67 <SubType>Code</SubType>
68 </Compile>
69 <Compile Include="Commands\Communication\EchoMasterCommand.cs" />
70 <Compile Include="Commands\Communication\IMCommand.cs" />
71 <Compile Include="Commands\Communication\SayCommand.cs" />
72 <Compile Include="Commands\Communication\ShoutCommand.cs" />
73 <Compile Include="Commands\Communication\WhisperCommand.cs" />
74 <Compile Include="Commands\System\MD5Command.cs" />
75 <Compile Include="Commands\Movement\FollowCommand.cs" />
76 <Compile Include="Commands\Movement\GotoCommand.cs" />
77 <Compile Include="Commands\Movement\JumpCommand.cs" />
78 <Compile Include="Commands\Movement\LocationCommand.cs" />
79 <Compile Include="Commands\Movement\SitCommand.cs" />
80 <Compile Include="Commands\System\PacketLogCommand.cs" />
81 <Compile Include="Commands\Land\ParcelInfoCommand.cs" />
82 <Compile Include="Commands\System\QuitCommand.cs">
83 <SubType>Code</SubType>
84 </Compile>
85 <Compile Include="Commands\Stats\RegionInfoCommand.cs" />
86 <Compile Include="Commands\System\SetMasterCommand.cs">
87 <SubType>Code</SubType>
88 </Compile>
89 <Compile Include="Commands\Prims\ExportCommand.cs" />
90 <Compile Include="Commands\Prims\ImportCommand.cs" />
91 <Compile Include="Commands\System\LoadCommand.cs" />
92 <Compile Include="Commands\Prims\PrimCountCommand.cs" />
93 <Compile Include="Commands\System\SetMasterKeyCommand.cs" />
94 <Compile Include="Commands\System\ShowEffectsCommand.cs" />
95 <Compile Include="Commands\Stats\StatsCommand.cs" />
96 <Compile Include="Commands\TouchCommand.cs" />
97 <Compile Include="Commands\TreeCommand.cs" />
98 <Compile Include="Commands\Stats\UptimeCommand.cs" />
99 <Compile Include="Commands\System\HelpCommand.cs" />
100 <Compile Include="ClientManager.cs" />
101 <Compile Include="Commands\WhoCommand.cs">
102 <SubType>Code</SubType>
103 </Compile>
104 <Compile Include="Parsing.cs" />
105 <Compile Include="Program.cs" />
106 <Compile Include="TestClient.cs" />
107 <Compile Include="Properties\AssemblyInfo.cs" />
108 </ItemGroup>
109 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
110 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
111 Other similar extension points exist, see Microsoft.Common.targets.
112 <Target Name="BeforeBuild">
113 </Target>
114 <Target Name="AfterBuild">
115 </Target>
116 -->
117 <PropertyGroup>
118 <PreBuildEvent>
119 </PreBuildEvent>
120 </PropertyGroup>
121</Project> \ No newline at end of file
diff --git a/tools/mass test client/MassTestClient.csproj.user b/tools/mass test client/MassTestClient.csproj.user
new file mode 100644
index 0000000..c32889c
--- /dev/null
+++ b/tools/mass test client/MassTestClient.csproj.user
@@ -0,0 +1,10 @@
1<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
3 <StartArguments>
4 </StartArguments>
5 </PropertyGroup>
6 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
7 <StartArguments>
8 </StartArguments>
9 </PropertyGroup>
10</Project> \ No newline at end of file
diff --git a/tools/mass test client/MassTestClient.sln b/tools/mass test client/MassTestClient.sln
new file mode 100644
index 0000000..cbbeef6
--- /dev/null
+++ b/tools/mass test client/MassTestClient.sln
@@ -0,0 +1,20 @@
1
2Microsoft Visual Studio Solution File, Format Version 9.00
3# Visual C# Express 2005
4Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassTestClient", "MassTestClient.csproj", "{B87682F6-B2D7-4C4D-A529-400C24FD4880}"
5EndProject
6Global
7 GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 Debug|Any CPU = Debug|Any CPU
9 Release|Any CPU = Release|Any CPU
10 EndGlobalSection
11 GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 {B87682F6-B2D7-4C4D-A529-400C24FD4880}.Release|Any CPU.Build.0 = Release|Any CPU
16 EndGlobalSection
17 GlobalSection(SolutionProperties) = preSolution
18 HideSolutionNode = FALSE
19 EndGlobalSection
20EndGlobal
diff --git a/tools/mass test client/MassTestClient.suo b/tools/mass test client/MassTestClient.suo
new file mode 100644
index 0000000..7f0637c
--- /dev/null
+++ b/tools/mass test client/MassTestClient.suo
Binary files differ
diff --git a/tools/mass test client/Parsing.cs b/tools/mass test client/Parsing.cs
new file mode 100644
index 0000000..371c3cd
--- /dev/null
+++ b/tools/mass test client/Parsing.cs
@@ -0,0 +1,61 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace libsecondlife.TestClient {
6 class Parsing {
7 public static string[] ParseArguments(string str) {
8 List<string> list = new List<string>();
9 string current = "";
10 string trimmed = null;
11 bool withinQuote = false;
12 bool escaped = false;
13 foreach (char c in str) {
14 if (c == '"') {
15 if (escaped) {
16 current += '"';
17 escaped = false;
18 } else {
19 current += '"';
20 withinQuote = !withinQuote;
21 }
22 } else if (c == ' ' || c == '\t') {
23 if (escaped || withinQuote) {
24 current += c;
25 escaped = false;
26 } else {
27 trimmed = current.Trim();
28 if (trimmed.StartsWith("\"") && trimmed.EndsWith("\"")) {
29 trimmed = trimmed.Remove(0, 1);
30 trimmed = trimmed.Remove(trimmed.Length - 1);
31 trimmed = trimmed.Trim();
32 }
33 if (trimmed.Length > 0)
34 list.Add(trimmed);
35 current = "";
36 }
37 } else if (c == '\\') {
38 if (escaped) {
39 current += '\\';
40 escaped = false;
41 } else {
42 escaped = true;
43 }
44 } else {
45 if (escaped)
46 throw new FormatException(c.ToString() + " is not an escapable character.");
47 current += c;
48 }
49 }
50 trimmed = current.Trim();
51 if (trimmed.StartsWith("\"") && trimmed.EndsWith("\"")) {
52 trimmed = trimmed.Remove(0, 1);
53 trimmed = trimmed.Remove(trimmed.Length - 1);
54 trimmed = trimmed.Trim();
55 }
56 if (trimmed.Length > 0)
57 list.Add(trimmed);
58 return list.ToArray();
59 }
60 }
61}
diff --git a/tools/mass test client/Program.cs b/tools/mass test client/Program.cs
new file mode 100644
index 0000000..6274011
--- /dev/null
+++ b/tools/mass test client/Program.cs
@@ -0,0 +1,218 @@
1using System;
2using System.Collections.Generic;
3using System.IO;
4using CommandLine.Utility;
5
6namespace libsecondlife.TestClient
7{
8 public class CommandLineArgumentsException : Exception
9 {
10 }
11
12 public class Program
13 {
14
15 private static void Usage()
16 {
17 Console.WriteLine("Usage: " + Environment.NewLine +
18 "MassTestClient.exe --first \"firstname\" --last \"lastname\" --pass \"password\" --contact \"youremail\" [--startpos \"sim/x/y/z\"] [--master \"master name\"] [--masterkey \"master uuid\"] [--loginuri \"loginuri\"] [--masscommandfile \"filename\"]" +
19 Environment.NewLine + Environment.NewLine + "MassTestClient.exe --loginfile \"filename\" --contact \"youremail\" [--master \"master name\"] [--masterkey \"master uuid\"] [--loginuri \"loginuri\"] [--masscommandfile \"filename\"]");
20 Console.ReadLine();
21 }
22
23 private static List<string> getMassTestCommands()
24 {
25 List<string> givenCommands = new List<string>();
26 Console.WriteLine("Please enter mass test commands to run in an infinite loop. Press enter to end the current command. Entering a blank command represents that you are done.");
27 Console.WriteLine("");
28
29 int curCommand = 0;
30 string lastCommand = "NULL";
31 while (lastCommand.Length > 0)
32 {
33 Console.Write("Command #" + curCommand + ">");
34 lastCommand = Console.ReadLine().Trim();
35 if (lastCommand.Length > 0)
36 {
37 givenCommands.Add(lastCommand);
38 curCommand++;
39 }
40 }
41
42 return givenCommands;
43 }
44
45 static void Main(string[] args)
46 {
47 Arguments arguments = new Arguments(args);
48
49 ClientManager manager;
50 List<LoginDetails> accounts = new List<LoginDetails>();
51 LoginDetails account;
52 string masterName = String.Empty;
53 LLUUID masterKey = LLUUID.Zero;
54 string file = String.Empty;
55 string contact = String.Empty;
56 string loginURI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
57 try
58 {
59 if (arguments["masterkey"] != null)
60 {
61 masterKey = LLUUID.Parse(arguments["masterkey"]);
62 }
63
64 if (arguments["master"] != null)
65 {
66 masterName = arguments["master"];
67 }
68
69 if (arguments["contact"] == null)
70 throw new CommandLineArgumentsException();
71
72 contact = arguments["contact"];
73
74 if (arguments["file"] != null)
75 {
76 file = arguments["file"];
77
78 // Loading names from a file
79 try
80 {
81 using (StreamReader reader = new StreamReader(file))
82 {
83 string line;
84 int lineNumber = 0;
85
86 while ((line = reader.ReadLine()) != null)
87 {
88 lineNumber++;
89 string[] tokens = line.Trim().Split(new char[] { ' ', ',' });
90
91 if (tokens.Length >= 3)
92 {
93 account = new LoginDetails();
94 account.FirstName = tokens[0];
95 account.LastName = tokens[1];
96 account.Password = tokens[2];
97
98 accounts.Add(account);
99
100 // Leaving this out until we have per-account masters (if that
101 // is desirable). For now the command-line option can
102 // specify the single master that TestClient supports
103
104 //if (tokens.Length == 5)
105 //{
106 // master = tokens[3] + " " + tokens[4];
107 //}
108 }
109 else
110 {
111 Console.WriteLine("Invalid data on line " + lineNumber +
112 ", must be in the format of: FirstName LastName Password");
113 }
114 }
115 }
116 }
117 catch (Exception e)
118 {
119 Console.WriteLine("Error reading from " + args[1]);
120 Console.WriteLine(e.ToString());
121 Console.ReadLine();
122 return;
123 }
124 }
125 else if (arguments["first"] != null && arguments["last"] != null && arguments["pass"] != null)
126 {
127 // Taking a single login off the command-line
128 account = new LoginDetails();
129 account.FirstName = arguments["first"];
130 account.LastName = arguments["last"];
131 account.Password = arguments["pass"];
132
133 accounts.Add(account);
134 }
135 else
136 {
137 throw new CommandLineArgumentsException();
138 }
139 }
140
141 catch (CommandLineArgumentsException)
142 {
143 Usage();
144 return;
145 }
146
147 if(arguments["loginuri"] != null)
148 {
149 loginURI = arguments["loginuri"];
150 }
151
152 List<string> massTestCommands = new List<string>();
153 if(arguments["masscommandfile"] != null)
154 {
155 string massCommandFile = arguments["masscommandfile"];
156 try
157 {
158 using (StreamReader reader = new StreamReader(massCommandFile))
159 {
160 string line;
161
162 while ((line = reader.ReadLine()) != null)
163 {
164
165 line = line.Trim();
166 if(line.Length > 0)
167 {
168 massTestCommands.Add(line);
169 }
170 }
171 }
172 }
173 catch (Exception e)
174 {
175 Console.WriteLine("Error reading from " + args[1]);
176 Console.WriteLine(e.ToString());
177 Console.ReadLine();
178 return;
179 }
180 }
181 else
182 {
183 Console.Clear();
184 massTestCommands = getMassTestCommands();
185 }
186
187 Console.Clear();
188 if (massTestCommands.Count == 0)
189 {
190 Console.WriteLine("No mass commands entered; Normal 'TestClient' operation will be used");
191 }
192 else
193 {
194 Console.WriteLine("Detected " + massTestCommands.Count + " mass commands; MassTestClient operation will be used");
195 }
196
197 foreach (LoginDetails a in accounts)
198 {
199 a.MasterName = masterName;
200 a.MasterKey = masterKey;
201 a.LoginURI = loginURI;
202 }
203
204 // Login the accounts and run the input loop
205 if (arguments["startpos"] != null)
206 {
207 manager = new ClientManager(accounts, contact, arguments["startpos"]);
208 }
209 else
210 {
211 manager = new ClientManager(accounts, contact);
212 }
213
214
215 manager.Run(massTestCommands);
216 }
217 }
218}
diff --git a/tools/mass test client/Properties/AssemblyInfo.cs b/tools/mass test client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ae311f4
--- /dev/null
+++ b/tools/mass test client/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("MassTestClient")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("")]
12[assembly: AssemblyProduct("MassTestClient")]
13[assembly: AssemblyCopyright("Copyright © 2007")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("0563f706-7fa9-42f6-bf23-c6acd1175964")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("1.0.0.0")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tools/mass test client/TestClient.build b/tools/mass test client/TestClient.build
new file mode 100644
index 0000000..803377b
--- /dev/null
+++ b/tools/mass test client/TestClient.build
@@ -0,0 +1,125 @@
1<?xml version="1.0"?>
2
3<project
4 name="libsecondlife"
5 default="build">
6
7 <!-- global framework settings -->
8 <property
9 name="target.framework"
10 value="${framework::get-target-framework()}" />
11 <property
12 name="assembly.dir"
13 value="${framework::get-assembly-directory(target.framework)}" />
14
15 <!-- global project settings -->
16 <xmlpeek
17 file="../../../libsecondlife.build"
18 xpath="/project/property[@name = 'project.version']/@value"
19 property="project.version" />
20 <property
21 name="build.number"
22 value="${math::abs(math::floor(timespan::get-total-days(datetime::now()
23 - datetime::parse('01/01/2002'))))}" />
24 <property
25 name="assembly"
26 value="TestClient"/>
27 <property
28 name="bin_dir"
29 value="../../../bin" />
30
31 <!-- default configuration -->
32 <property
33 name="project.config"
34 value="debug" /> <!-- debug|release -->
35
36 <!-- named configurations -->
37 <target
38 name="init"
39 description="Initializes build properties">
40 <call target="${project.config}" />
41 </target>
42
43 <target
44 name="debug"
45 description="configures a debug build">
46 <property
47 name="build.debug"
48 value="true" />
49 <property
50 name="package.name"
51 value="${project::get-name()}-${project.version}-${project.config}" />
52 <property
53 name="assembly.configuration"
54 value="${framework::get-target-framework()}.${platform::get-name()} [${project.config}]" />
55 </target>
56
57 <target
58 name="release"
59 description="configures a release build">
60 <property
61 name="project.config"
62 value="release" />
63 <property
64 name="build.debug"
65 value="false" />
66 <property
67 name="package.name"
68 value="${project::get-name()}-${project.version}" />
69 <property
70 name="assembly.configuration"
71 value="${framework::get-target-framework()}.${platform::get-name()}" />
72 </target>
73
74 <!-- build tasks -->
75 <target
76 name="build"
77 depends="init"
78 description="Builds the binaries for the current configuration">
79 <echo message="Build Directory is ${bin_dir}/" />
80 <mkdir
81 dir="${bin_dir}"
82 failonerror="false" />
83 <csc
84 target="exe"
85 debug="${build.debug}"
86 output="${bin_dir}/${assembly}.exe">
87 <sources failonempty="true">
88 <include name="*.cs" />
89 <include name="Commands/**.cs" />
90 <exclude name="Commands/Communication/TtsCommand.cs" />
91 </sources>
92 <references basedir="${bin_dir}/">
93 <include name="libsecondlife.dll"/>
94 <include name="openjpegnet.dll"/>
95 </references>
96 </csc>
97 </target>
98
99 <target
100 name="build-dll"
101 description="Builds libsecondlife dll">
102 <nant
103 buildfile="../../libsecondlife-cs/libsecondlife.build"
104 target="${project.config} build"/>
105 </target>
106
107 <target
108 name="clean"
109 depends="init"
110 description="Deletes the current configuration">
111 <delete failonerror="false">
112 <fileset basedir="${bin_dir}/">
113 <include name="${assembly}.exe" />
114 <include name="${assembly}.pdb" />
115 <include name="**/${assembly}.*.resources" />
116 </fileset>
117 </delete>
118 </target>
119
120 <target
121 name="*"
122 description="Handles unknown targets">
123 <echo message="skip" />
124 </target>
125</project>
diff --git a/tools/mass test client/TestClient.cs b/tools/mass test client/TestClient.cs
new file mode 100644
index 0000000..cee218c
--- /dev/null
+++ b/tools/mass test client/TestClient.cs
@@ -0,0 +1,324 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.Xml;
5using libsecondlife;
6using libsecondlife.Packets;
7using libsecondlife.AssetSystem;
8
9namespace libsecondlife.TestClient
10{
11 public class TestClient : SecondLife
12 {
13 public delegate void PrimCreatedCallback(Simulator simulator, Primitive prim);
14
15 public event PrimCreatedCallback OnPrimCreated;
16
17 public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims;
18 public LLUUID GroupID = LLUUID.Zero;
19 public Dictionary<LLUUID, GroupMember> GroupMembers;
20 public Dictionary<uint, Avatar> AvatarList = new Dictionary<uint,Avatar>();
21 public Dictionary<LLUUID, AvatarAppearancePacket> Appearances = new Dictionary<LLUUID, AvatarAppearancePacket>();
22 public Dictionary<string, Command> Commands = new Dictionary<string,Command>();
23 public bool Running = true;
24 public string MasterName = String.Empty;
25 public LLUUID MasterKey = LLUUID.Zero;
26 public ClientManager ClientManager;
27 public int regionX;
28 public int regionY;
29
30 //internal libsecondlife.InventorySystem.InventoryFolder currentDirectory;
31
32 private System.Timers.Timer updateTimer;
33
34
35 /// <summary>
36 ///
37 /// </summary>
38 public TestClient(ClientManager manager)
39 {
40 ClientManager = manager;
41
42 updateTimer = new System.Timers.Timer(1000);
43 updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed);
44
45 RegisterAllCommands(Assembly.GetExecutingAssembly());
46
47 Settings.DEBUG = true;
48 Settings.STORE_LAND_PATCHES = true;
49 Settings.ALWAYS_REQUEST_OBJECTS = true;
50
51 Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler));
52
53 Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim);
54 Objects.OnObjectUpdated += new ObjectManager.ObjectUpdatedCallback(Objects_OnObjectUpdated);
55 Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(Objects_OnObjectKilled);
56 Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar);
57 Self.OnInstantMessage += new MainAvatar.InstantMessageCallback(Self_OnInstantMessage);
58 Groups.OnGroupMembers += new GroupManager.GroupMembersCallback(GroupMembersHandler);
59 this.OnLogMessage += new LogCallback(TestClient_OnLogMessage);
60
61 Network.RegisterCallback(PacketType.AvatarAppearance, new NetworkManager.PacketCallback(AvatarAppearanceHandler));
62
63 updateTimer.Start();
64 }
65
66 public void RegisterAllCommands(Assembly assembly)
67 {
68 foreach (Type t in assembly.GetTypes())
69 {
70 try
71 {
72 if (t.IsSubclassOf(typeof(Command)))
73 {
74 ConstructorInfo info = t.GetConstructor(new Type[] { typeof(TestClient) });
75 Command command = (Command)info.Invoke(new object[] { this });
76 RegisterCommand(command);
77 }
78 }
79 catch (Exception e)
80 {
81 Console.WriteLine(e.ToString());
82 }
83 }
84 }
85
86 public void RegisterCommand(Command command)
87 {
88 command.Client = this;
89 if (!Commands.ContainsKey(command.Name.ToLower()))
90 {
91 Commands.Add(command.Name.ToLower(), command);
92 }
93 }
94
95 //breaks up large responses to deal with the max IM size
96 private void SendResponseIM(SecondLife client, LLUUID fromAgentID, string data, LLUUID imSessionID)
97 {
98 for ( int i = 0 ; i < data.Length ; i += 1024 ) {
99 int y;
100 if ((i + 1023) > data.Length)
101 {
102 y = data.Length - i;
103 }
104 else
105 {
106 y = 1023;
107 }
108 string message = data.Substring(i, y);
109 client.Self.InstantMessage(fromAgentID, message, imSessionID);
110 }
111 }
112
113 public void DoCommand(string cmd, LLUUID fromAgentID, LLUUID imSessionID)
114 {
115 string[] tokens = Parsing.ParseArguments(cmd);
116
117 if (tokens.Length == 0)
118 return;
119
120 string firstToken = tokens[0].ToLower();
121
122 // "all balance" will send the balance command to all currently logged in bots
123 if (firstToken == "all" && tokens.Length > 1)
124 {
125 cmd = String.Empty;
126
127 // Reserialize all of the arguments except for "all"
128 for (int i = 1; i < tokens.Length; i++)
129 {
130 cmd += tokens[i] + " ";
131 }
132
133 ClientManager.DoCommandAll(cmd, fromAgentID, imSessionID);
134
135 return;
136 }
137
138 if (Commands.ContainsKey(firstToken))
139 {
140 string[] args = new string[tokens.Length - 1];
141 Array.Copy(tokens, 1, args, 0, args.Length);
142 string response = Commands[firstToken].Execute(args, fromAgentID);
143
144 if (response.Length > 0)
145 {
146 Console.WriteLine(response);
147
148 if (fromAgentID != null && Network.Connected)
149 {
150 // IMs don't like \r\n line endings, clean them up first
151 response = response.Replace("\r", "");
152 SendResponseIM(this, fromAgentID, response, imSessionID);
153 }
154 }
155 }
156 }
157
158 private void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
159 {
160 foreach (Command c in Commands.Values)
161 if (c.Active)
162 c.Think();
163 }
164
165 private void AgentDataUpdateHandler(Packet packet, Simulator sim)
166 {
167 AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet;
168 if (p.AgentData.AgentID == sim.Client.Network.AgentID)
169 {
170 Console.WriteLine("Got the group ID for " + sim.Client.ToString() + ", requesting group members...");
171 GroupID = p.AgentData.ActiveGroupID;
172
173 sim.Client.Groups.BeginGetGroupMembers(GroupID);
174 }
175 }
176
177 private void TestClient_OnLogMessage(string message, Helpers.LogLevel level)
178 {
179 Console.WriteLine("<" + this.ToString() + "> " + level.ToString() + ": " + message);
180 }
181
182 private void GroupMembersHandler(Dictionary<LLUUID, GroupMember> members)
183 {
184 Console.WriteLine("Got " + members.Count + " group members.");
185 GroupMembers = members;
186 }
187
188 private void Objects_OnObjectKilled(Simulator simulator, uint objectID)
189 {
190 lock (SimPrims)
191 {
192 if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(objectID))
193 SimPrims[simulator].Remove(objectID);
194 }
195
196 lock (AvatarList)
197 {
198 if (AvatarList.ContainsKey(objectID))
199 AvatarList.Remove(objectID);
200 }
201 }
202
203 private void Objects_OnObjectUpdated(Simulator simulator, ObjectUpdate update, ulong regionHandle, ushort timeDilation)
204 {
205 regionX = (int)(regionHandle >> 32);
206 regionY = (int)(regionHandle & 0xFFFFFFFF);
207
208 if (update.Avatar)
209 {
210 lock (AvatarList)
211 {
212 // TODO: We really need a solid avatar and object tracker in Utilities to use here
213 if (AvatarList.ContainsKey(update.LocalID))
214 {
215 AvatarList[update.LocalID].CollisionPlane = update.CollisionPlane;
216 AvatarList[update.LocalID].Position = update.Position;
217 AvatarList[update.LocalID].Velocity = update.Velocity;
218 AvatarList[update.LocalID].Acceleration = update.Acceleration;
219 AvatarList[update.LocalID].Rotation = update.Rotation;
220 AvatarList[update.LocalID].AngularVelocity = update.AngularVelocity;
221 AvatarList[update.LocalID].Textures = update.Textures;
222 }
223 }
224 }
225 else
226 {
227 lock (SimPrims)
228 {
229 if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(update.LocalID))
230 {
231 SimPrims[simulator][update.LocalID].Position = update.Position;
232 SimPrims[simulator][update.LocalID].Velocity = update.Velocity;
233 SimPrims[simulator][update.LocalID].Acceleration = update.Acceleration;
234 SimPrims[simulator][update.LocalID].Rotation = update.Rotation;
235 SimPrims[simulator][update.LocalID].AngularVelocity = update.AngularVelocity;
236 SimPrims[simulator][update.LocalID].Textures = update.Textures;
237 }
238 }
239 }
240 }
241
242 private void Objects_OnNewPrim(Simulator simulator, Primitive prim, ulong regionHandle, ushort timeDilation)
243 {
244 lock (SimPrims)
245 {
246 if (!SimPrims.ContainsKey(simulator))
247 {
248 SimPrims[simulator] = new Dictionary<uint, Primitive>(10000);
249 }
250
251 SimPrims[simulator][prim.LocalID] = prim;
252 }
253
254 if ((prim.Flags & LLObject.ObjectFlags.CreateSelected) != 0 && OnPrimCreated != null)
255 {
256 OnPrimCreated(simulator, prim);
257 }
258 }
259
260 private void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation)
261 {
262 lock (AvatarList)
263 {
264 AvatarList[avatar.LocalID] = avatar;
265 }
266 }
267
268 private void AvatarAppearanceHandler(Packet packet, Simulator simulator)
269 {
270 AvatarAppearancePacket appearance = (AvatarAppearancePacket)packet;
271
272 lock (Appearances) Appearances[appearance.Sender.ID] = appearance;
273 }
274
275 private void Self_OnInstantMessage(LLUUID fromAgentID, string fromAgentName, LLUUID toAgentID,
276 uint parentEstateID, LLUUID regionID, LLVector3 position, MainAvatar.InstantMessageDialog dialog,
277 bool groupIM, LLUUID imSessionID, DateTime timestamp, string message,
278 MainAvatar.InstantMessageOnline offline, byte[] binaryBucket)
279 {
280 if (MasterKey != LLUUID.Zero)
281 {
282 if (fromAgentID != MasterKey)
283 {
284 // Received an IM from someone that is not the bot's master, ignore
285 Console.WriteLine("<IM>" + fromAgentName + " (not master): " + message + "@" + regionID.ToString() + ":" + position.ToString() );
286 return;
287 }
288 }
289 else
290 {
291 if (GroupMembers != null && !GroupMembers.ContainsKey(fromAgentID))
292 {
293 // Received an IM from someone outside the bot's group, ignore
294 Console.WriteLine("<IM>" + fromAgentName + " (not in group): " + message + "@" + regionID.ToString() + ":" + position.ToString());
295 return;
296 }
297 }
298
299 Console.WriteLine("<IM>" + fromAgentName + ": " + message);
300
301 if (dialog == MainAvatar.InstantMessageDialog.RequestTeleport)
302 {
303 Console.WriteLine("Accepting teleport lure.");
304 Self.TeleportLureRespond(fromAgentID, true);
305 }
306 else
307 {
308 if (dialog == MainAvatar.InstantMessageDialog.InventoryOffered)
309 {
310 Console.WriteLine("Accepting inventory offer.");
311
312 Self.InstantMessage(Self.FirstName + " " + Self.LastName, fromAgentID, String.Empty,
313 imSessionID, MainAvatar.InstantMessageDialog.InventoryAccepted,
314 MainAvatar.InstantMessageOnline.Offline, Self.Position, LLUUID.Zero,
315 Self.InventoryRootFolderUUID.GetBytes());
316 }
317 else
318 {
319 DoCommand(message, fromAgentID, imSessionID);
320 }
321 }
322 }
323 }
324}
diff --git a/tools/mass test client/bin/libsecondlife.Utilities.dll b/tools/mass test client/bin/libsecondlife.Utilities.dll
new file mode 100644
index 0000000..b5a71fc
--- /dev/null
+++ b/tools/mass test client/bin/libsecondlife.Utilities.dll
Binary files differ
diff --git a/tools/mass test client/bin/libsecondlife.dll b/tools/mass test client/bin/libsecondlife.dll
new file mode 100644
index 0000000..60c3151
--- /dev/null
+++ b/tools/mass test client/bin/libsecondlife.dll
Binary files differ
diff --git a/tools/mass test client/bin/openjpegnet.dll b/tools/mass test client/bin/openjpegnet.dll
new file mode 100644
index 0000000..83067b0
--- /dev/null
+++ b/tools/mass test client/bin/openjpegnet.dll
Binary files differ