diff options
author | gareth | 2007-05-08 00:10:04 +0000 |
---|---|---|
committer | gareth | 2007-05-08 00:10:04 +0000 |
commit | 5b6afeafbc249ba88dcc20d1fbc98ce12418b21b (patch) | |
tree | 78861e5f6ae871d63c83b4ab1cc4c55ea184ed6d /ExportBot/Commands | |
parent | ZOMG! (diff) | |
download | opensim-SC-5b6afeafbc249ba88dcc20d1fbc98ce12418b21b.zip opensim-SC-5b6afeafbc249ba88dcc20d1fbc98ce12418b21b.tar.gz opensim-SC-5b6afeafbc249ba88dcc20d1fbc98ce12418b21b.tar.bz2 opensim-SC-5b6afeafbc249ba88dcc20d1fbc98ce12418b21b.tar.xz |
Brought in TestClient code for teh fork
Diffstat (limited to 'ExportBot/Commands')
48 files changed, 2712 insertions, 0 deletions
diff --git a/ExportBot/Commands/AppearanceCommand.cs b/ExportBot/Commands/AppearanceCommand.cs new file mode 100644 index 0000000..6f003a7 --- /dev/null +++ b/ExportBot/Commands/AppearanceCommand.cs | |||
@@ -0,0 +1,29 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/CloneProfileCommand.cs b/ExportBot/Commands/CloneProfileCommand.cs new file mode 100644 index 0000000..d7fb5fc --- /dev/null +++ b/ExportBot/Commands/CloneProfileCommand.cs | |||
@@ -0,0 +1,131 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Threading; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Communication/EchoMasterCommand.cs b/ExportBot/Commands/Communication/EchoMasterCommand.cs new file mode 100644 index 0000000..2e426a8 --- /dev/null +++ b/ExportBot/Commands/Communication/EchoMasterCommand.cs | |||
@@ -0,0 +1,42 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Communication/IMCommand.cs b/ExportBot/Commands/Communication/IMCommand.cs new file mode 100644 index 0000000..32d7fff --- /dev/null +++ b/ExportBot/Commands/Communication/IMCommand.cs | |||
@@ -0,0 +1,71 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Threading; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Communication/SayCommand.cs b/ExportBot/Commands/Communication/SayCommand.cs new file mode 100644 index 0000000..d5717a6 --- /dev/null +++ b/ExportBot/Commands/Communication/SayCommand.cs | |||
@@ -0,0 +1,44 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | |||
6 | namespace 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/ExportBot/Commands/Communication/ShoutCommand.cs b/ExportBot/Commands/Communication/ShoutCommand.cs new file mode 100644 index 0000000..cf4b6c5 --- /dev/null +++ b/ExportBot/Commands/Communication/ShoutCommand.cs | |||
@@ -0,0 +1,49 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Communication/TtsCommand.cs b/ExportBot/Commands/Communication/TtsCommand.cs new file mode 100644 index 0000000..e8bd122 --- /dev/null +++ b/ExportBot/Commands/Communication/TtsCommand.cs | |||
@@ -0,0 +1,51 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using System.Speech.Synthesis; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Packets; | ||
7 | using 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 | |||
13 | namespace 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/ExportBot/Commands/Communication/WhisperCommand.cs b/ExportBot/Commands/Communication/WhisperCommand.cs new file mode 100644 index 0000000..89ba0f3 --- /dev/null +++ b/ExportBot/Commands/Communication/WhisperCommand.cs | |||
@@ -0,0 +1,49 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/DebugCommand.cs b/ExportBot/Commands/DebugCommand.cs new file mode 100644 index 0000000..fbfde7c --- /dev/null +++ b/ExportBot/Commands/DebugCommand.cs | |||
@@ -0,0 +1,37 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using libsecondlife; | ||
4 | using libsecondlife.Packets; | ||
5 | |||
6 | namespace 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/ExportBot/Commands/DilationCommand.cs b/ExportBot/Commands/DilationCommand.cs new file mode 100644 index 0000000..c1d3c04 --- /dev/null +++ b/ExportBot/Commands/DilationCommand.cs | |||
@@ -0,0 +1,22 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/DumpOutfitCommand.cs b/ExportBot/Commands/DumpOutfitCommand.cs new file mode 100644 index 0000000..2d3d0d8 --- /dev/null +++ b/ExportBot/Commands/DumpOutfitCommand.cs | |||
@@ -0,0 +1,98 @@ | |||
1 | using System; | ||
2 | using System.Text; | ||
3 | using System.IO; | ||
4 | using System.Collections.Generic; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Utilities.Assets; | ||
7 | using libsecondlife.Utilities.Appearance; | ||
8 | |||
9 | namespace 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/ExportBot/Commands/ExportCommand.cs b/ExportBot/Commands/ExportCommand.cs new file mode 100644 index 0000000..2baac1a --- /dev/null +++ b/ExportBot/Commands/ExportCommand.cs | |||
@@ -0,0 +1,209 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Xml; | ||
5 | using System.Text; | ||
6 | using System.Threading; | ||
7 | using libsecondlife; | ||
8 | using libsecondlife.Packets; | ||
9 | |||
10 | namespace 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/ExportBot/Commands/ExportOutfitCommand.cs b/ExportBot/Commands/ExportOutfitCommand.cs new file mode 100644 index 0000000..6ec2776 --- /dev/null +++ b/ExportBot/Commands/ExportOutfitCommand.cs | |||
@@ -0,0 +1,66 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Xml; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Packets; | ||
7 | |||
8 | namespace 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/ExportBot/Commands/ExportParticlesCommand.cs b/ExportBot/Commands/ExportParticlesCommand.cs new file mode 100644 index 0000000..4b2c322 --- /dev/null +++ b/ExportBot/Commands/ExportParticlesCommand.cs | |||
@@ -0,0 +1,119 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Text; | ||
5 | using libsecondlife; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/FindSimCommand.cs b/ExportBot/Commands/FindSimCommand.cs new file mode 100644 index 0000000..c6cc9c4 --- /dev/null +++ b/ExportBot/Commands/FindSimCommand.cs | |||
@@ -0,0 +1,43 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/HelpCommand.cs b/ExportBot/Commands/HelpCommand.cs new file mode 100644 index 0000000..5cbdcb2 --- /dev/null +++ b/ExportBot/Commands/HelpCommand.cs | |||
@@ -0,0 +1,29 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/ImportCommand.cs b/ExportBot/Commands/ImportCommand.cs new file mode 100644 index 0000000..4cdcaee --- /dev/null +++ b/ExportBot/Commands/ImportCommand.cs | |||
@@ -0,0 +1,246 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Xml; | ||
4 | using System.Xml.Serialization; | ||
5 | using System.Threading; | ||
6 | using System.IO; | ||
7 | using libsecondlife; | ||
8 | |||
9 | namespace 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/ExportBot/Commands/ImportOutfitCommand.cs b/ExportBot/Commands/ImportOutfitCommand.cs new file mode 100644 index 0000000..5ac7b8a --- /dev/null +++ b/ExportBot/Commands/ImportOutfitCommand.cs | |||
@@ -0,0 +1,66 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Xml; | ||
5 | using System.Xml.Serialization; | ||
6 | using libsecondlife; | ||
7 | using libsecondlife.Packets; | ||
8 | |||
9 | namespace 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/ExportBot/Commands/Inventory/BalanceCommand.cs b/ExportBot/Commands/Inventory/BalanceCommand.cs new file mode 100644 index 0000000..92e9b39 --- /dev/null +++ b/ExportBot/Commands/Inventory/BalanceCommand.cs | |||
@@ -0,0 +1,21 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using libsecondlife; | ||
4 | using libsecondlife.Packets; | ||
5 | |||
6 | namespace 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/ExportBot/Commands/Inventory/DeleteFolderCommand.cs b/ExportBot/Commands/Inventory/DeleteFolderCommand.cs new file mode 100644 index 0000000..ddbb86c --- /dev/null +++ b/ExportBot/Commands/Inventory/DeleteFolderCommand.cs | |||
@@ -0,0 +1,43 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Text; | ||
5 | using System.Threading; | ||
6 | using System.Xml; | ||
7 | using System.Xml.Serialization; | ||
8 | |||
9 | using libsecondlife; | ||
10 | using libsecondlife.Packets; | ||
11 | using libsecondlife.InventorySystem; | ||
12 | |||
13 | namespace 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/ExportBot/Commands/Inventory/GiveAllCommand.cs b/ExportBot/Commands/Inventory/GiveAllCommand.cs new file mode 100644 index 0000000..fe42fce --- /dev/null +++ b/ExportBot/Commands/Inventory/GiveAllCommand.cs | |||
@@ -0,0 +1,27 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Inventory/InventoryCommand.cs b/ExportBot/Commands/Inventory/InventoryCommand.cs new file mode 100644 index 0000000..7b01bb1 --- /dev/null +++ b/ExportBot/Commands/Inventory/InventoryCommand.cs | |||
@@ -0,0 +1,62 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Text; | ||
5 | using System.Threading; | ||
6 | using System.Xml; | ||
7 | using System.Xml.Serialization; | ||
8 | |||
9 | using libsecondlife; | ||
10 | using libsecondlife.Packets; | ||
11 | using libsecondlife.InventorySystem; | ||
12 | |||
13 | namespace 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/ExportBot/Commands/Inventory/WearCommand.cs b/ExportBot/Commands/Inventory/WearCommand.cs new file mode 100644 index 0000000..d1bc32c --- /dev/null +++ b/ExportBot/Commands/Inventory/WearCommand.cs | |||
@@ -0,0 +1,43 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.IO; | ||
4 | using System.Text; | ||
5 | using System.Threading; | ||
6 | using System.Xml; | ||
7 | using System.Xml.Serialization; | ||
8 | |||
9 | using libsecondlife; | ||
10 | using libsecondlife.Packets; | ||
11 | using libsecondlife.InventorySystem; | ||
12 | |||
13 | namespace 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."; | ||
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 | // Client.Appearance.WearOutfit(folder); | ||
37 | // return "Outfit " + target + " worn."; | ||
38 | //} | ||
39 | |||
40 | //return "Unable to find: " + target; | ||
41 | } | ||
42 | } | ||
43 | } \ No newline at end of file | ||
diff --git a/ExportBot/Commands/LoadCommand.cs b/ExportBot/Commands/LoadCommand.cs new file mode 100644 index 0000000..70dada4 --- /dev/null +++ b/ExportBot/Commands/LoadCommand.cs | |||
@@ -0,0 +1,28 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using System.Reflection; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Packets; | ||
7 | |||
8 | namespace 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/ExportBot/Commands/LoginCommand.cs b/ExportBot/Commands/LoginCommand.cs new file mode 100644 index 0000000..64675f5 --- /dev/null +++ b/ExportBot/Commands/LoginCommand.cs | |||
@@ -0,0 +1,34 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Reflection; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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.LoginStatusMessage; | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | } | ||
diff --git a/ExportBot/Commands/LogoutCommand.cs b/ExportBot/Commands/LogoutCommand.cs new file mode 100644 index 0000000..cdb5bde --- /dev/null +++ b/ExportBot/Commands/LogoutCommand.cs | |||
@@ -0,0 +1,24 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/MD5Command.cs b/ExportBot/Commands/MD5Command.cs new file mode 100644 index 0000000..0a2ee5d --- /dev/null +++ b/ExportBot/Commands/MD5Command.cs | |||
@@ -0,0 +1,22 @@ | |||
1 | using System; | ||
2 | using libsecondlife; | ||
3 | |||
4 | namespace 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/ExportBot/Commands/Movement/FollowCommand.cs b/ExportBot/Commands/Movement/FollowCommand.cs new file mode 100644 index 0000000..f5074a3 --- /dev/null +++ b/ExportBot/Commands/Movement/FollowCommand.cs | |||
@@ -0,0 +1,90 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/GotoCommand.cs b/ExportBot/Commands/Movement/GotoCommand.cs new file mode 100644 index 0000000..df2b8a7 --- /dev/null +++ b/ExportBot/Commands/Movement/GotoCommand.cs | |||
@@ -0,0 +1,53 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/JumpCommand.cs b/ExportBot/Commands/Movement/JumpCommand.cs new file mode 100644 index 0000000..29b11a0 --- /dev/null +++ b/ExportBot/Commands/Movement/JumpCommand.cs | |||
@@ -0,0 +1,34 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/LocationCommand.cs b/ExportBot/Commands/Movement/LocationCommand.cs new file mode 100644 index 0000000..2fd62bb --- /dev/null +++ b/ExportBot/Commands/Movement/LocationCommand.cs | |||
@@ -0,0 +1,23 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/MoveToCommand.cs b/ExportBot/Commands/Movement/MoveToCommand.cs new file mode 100644 index 0000000..6d0a225 --- /dev/null +++ b/ExportBot/Commands/Movement/MoveToCommand.cs | |||
@@ -0,0 +1,24 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | |||
5 | namespace 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/ExportBot/Commands/Movement/SitCommand.cs b/ExportBot/Commands/Movement/SitCommand.cs new file mode 100644 index 0000000..b9ef6be --- /dev/null +++ b/ExportBot/Commands/Movement/SitCommand.cs | |||
@@ -0,0 +1,52 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/SitOnCommand.cs b/ExportBot/Commands/Movement/SitOnCommand.cs new file mode 100644 index 0000000..ec9d201 --- /dev/null +++ b/ExportBot/Commands/Movement/SitOnCommand.cs | |||
@@ -0,0 +1,54 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/Movement/StandCommand.cs b/ExportBot/Commands/Movement/StandCommand.cs new file mode 100644 index 0000000..8a00552 --- /dev/null +++ b/ExportBot/Commands/Movement/StandCommand.cs | |||
@@ -0,0 +1,47 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/PacketLogCommand.cs b/ExportBot/Commands/PacketLogCommand.cs new file mode 100644 index 0000000..827b147 --- /dev/null +++ b/ExportBot/Commands/PacketLogCommand.cs | |||
@@ -0,0 +1,84 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Xml; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/ParcelInfoCommand.cs b/ExportBot/Commands/ParcelInfoCommand.cs new file mode 100644 index 0000000..e4108a9 --- /dev/null +++ b/ExportBot/Commands/ParcelInfoCommand.cs | |||
@@ -0,0 +1,62 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Threading; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Utilities; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/PrimCountCommand.cs b/ExportBot/Commands/PrimCountCommand.cs new file mode 100644 index 0000000..8adc563 --- /dev/null +++ b/ExportBot/Commands/PrimCountCommand.cs | |||
@@ -0,0 +1,32 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/QuitCommand.cs b/ExportBot/Commands/QuitCommand.cs new file mode 100644 index 0000000..4cd7209 --- /dev/null +++ b/ExportBot/Commands/QuitCommand.cs | |||
@@ -0,0 +1,24 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/RegionInfoCommand.cs b/ExportBot/Commands/RegionInfoCommand.cs new file mode 100644 index 0000000..7581137 --- /dev/null +++ b/ExportBot/Commands/RegionInfoCommand.cs | |||
@@ -0,0 +1,45 @@ | |||
1 | using System; | ||
2 | using System.Text; | ||
3 | using libsecondlife; | ||
4 | |||
5 | namespace 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/ExportBot/Commands/SetMasterCommand.cs b/ExportBot/Commands/SetMasterCommand.cs new file mode 100644 index 0000000..a6ecbdc --- /dev/null +++ b/ExportBot/Commands/SetMasterCommand.cs | |||
@@ -0,0 +1,73 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using System.Threading; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Packets; | ||
7 | |||
8 | namespace 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); | ||
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/ExportBot/Commands/SetMasterKeyCommand.cs b/ExportBot/Commands/SetMasterKeyCommand.cs new file mode 100644 index 0000000..0085f79 --- /dev/null +++ b/ExportBot/Commands/SetMasterKeyCommand.cs | |||
@@ -0,0 +1,35 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/ShowEffectsCommand.cs b/ExportBot/Commands/ShowEffectsCommand.cs new file mode 100644 index 0000000..c0b20a7 --- /dev/null +++ b/ExportBot/Commands/ShowEffectsCommand.cs | |||
@@ -0,0 +1,76 @@ | |||
1 | using System; | ||
2 | using libsecondlife; | ||
3 | |||
4 | namespace 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/ExportBot/Commands/StatsCommand.cs b/ExportBot/Commands/StatsCommand.cs new file mode 100644 index 0000000..7835ec8 --- /dev/null +++ b/ExportBot/Commands/StatsCommand.cs | |||
@@ -0,0 +1,39 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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 | |||
34 | output.Append("Packets in the queue: " + Client.Network.InboxCount); | ||
35 | |||
36 | return output.ToString(); | ||
37 | } | ||
38 | } | ||
39 | } | ||
diff --git a/ExportBot/Commands/TouchCommand.cs b/ExportBot/Commands/TouchCommand.cs new file mode 100644 index 0000000..4103d21 --- /dev/null +++ b/ExportBot/Commands/TouchCommand.cs | |||
@@ -0,0 +1,55 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/TreeCommand.cs b/ExportBot/Commands/TreeCommand.cs new file mode 100644 index 0000000..2029e37 --- /dev/null +++ b/ExportBot/Commands/TreeCommand.cs | |||
@@ -0,0 +1,51 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/UptimeCommand.cs b/ExportBot/Commands/UptimeCommand.cs new file mode 100644 index 0000000..3edec73 --- /dev/null +++ b/ExportBot/Commands/UptimeCommand.cs | |||
@@ -0,0 +1,25 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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/ExportBot/Commands/WhoCommand.cs b/ExportBot/Commands/WhoCommand.cs new file mode 100644 index 0000000..83d8610 --- /dev/null +++ b/ExportBot/Commands/WhoCommand.cs | |||
@@ -0,0 +1,29 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using libsecondlife; | ||
5 | using libsecondlife.Packets; | ||
6 | |||
7 | namespace 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 | } | ||