diff options
Diffstat (limited to 'ExportBot/TestClient.cs')
-rw-r--r-- | ExportBot/TestClient.cs | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/ExportBot/TestClient.cs b/ExportBot/TestClient.cs new file mode 100644 index 0000000..cf8783e --- /dev/null +++ b/ExportBot/TestClient.cs | |||
@@ -0,0 +1,328 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Reflection; | ||
4 | using System.Xml; | ||
5 | using libsecondlife; | ||
6 | using libsecondlife.Packets; | ||
7 | using libsecondlife.AssetSystem; | ||
8 | |||
9 | namespace libsecondlife.TestClient | ||
10 | { | ||
11 | public class TestClient : SecondLife | ||
12 | { | ||
13 | public delegate void PrimCreatedCallback(Simulator simulator, Primitive prim); | ||
14 | |||
15 | public event PrimCreatedCallback OnPrimCreated; | ||
16 | |||
17 | public Dictionary<Simulator, Dictionary<uint, Primitive>> SimPrims; | ||
18 | public LLUUID GroupID = LLUUID.Zero; | ||
19 | public Dictionary<LLUUID, GroupMember> GroupMembers; | ||
20 | public Dictionary<uint, Avatar> AvatarList = new Dictionary<uint,Avatar>(); | ||
21 | public Dictionary<LLUUID, AvatarAppearancePacket> Appearances = new Dictionary<LLUUID, AvatarAppearancePacket>(); | ||
22 | public Dictionary<string, Command> Commands = new Dictionary<string,Command>(); | ||
23 | public bool Running = true; | ||
24 | public string MasterName = String.Empty; | ||
25 | public LLUUID MasterKey = LLUUID.Zero; | ||
26 | public ClientManager ClientManager; | ||
27 | public int regionX; | ||
28 | public int regionY; | ||
29 | |||
30 | //internal libsecondlife.InventorySystem.InventoryFolder currentDirectory; | ||
31 | |||
32 | private LLQuaternion bodyRotation = LLQuaternion.Identity; | ||
33 | private LLVector3 forward = new LLVector3(0, 0.9999f, 0); | ||
34 | private LLVector3 left = new LLVector3(0.9999f, 0, 0); | ||
35 | private LLVector3 up = new LLVector3(0, 0, 0.9999f); | ||
36 | private System.Timers.Timer updateTimer; | ||
37 | |||
38 | |||
39 | /// <summary> | ||
40 | /// | ||
41 | /// </summary> | ||
42 | public TestClient(ClientManager manager) | ||
43 | { | ||
44 | ClientManager = manager; | ||
45 | |||
46 | updateTimer = new System.Timers.Timer(1000); | ||
47 | updateTimer.Elapsed += new System.Timers.ElapsedEventHandler(updateTimer_Elapsed); | ||
48 | |||
49 | RegisterAllCommands(Assembly.GetExecutingAssembly()); | ||
50 | |||
51 | Settings.DEBUG = true; | ||
52 | Settings.STORE_LAND_PATCHES = true; | ||
53 | Settings.ALWAYS_REQUEST_OBJECTS = true; | ||
54 | |||
55 | Network.RegisterCallback(PacketType.AgentDataUpdate, new NetworkManager.PacketCallback(AgentDataUpdateHandler)); | ||
56 | |||
57 | Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim); | ||
58 | Objects.OnObjectUpdated += new ObjectManager.ObjectUpdatedCallback(Objects_OnObjectUpdated); | ||
59 | Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(Objects_OnObjectKilled); | ||
60 | Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar); | ||
61 | Self.OnInstantMessage += new MainAvatar.InstantMessageCallback(Self_OnInstantMessage); | ||
62 | Groups.OnGroupMembers += new GroupManager.GroupMembersCallback(GroupMembersHandler); | ||
63 | this.OnLogMessage += new LogCallback(TestClient_OnLogMessage); | ||
64 | |||
65 | Network.RegisterCallback(PacketType.AvatarAppearance, new NetworkManager.PacketCallback(AvatarAppearanceHandler)); | ||
66 | |||
67 | updateTimer.Start(); | ||
68 | } | ||
69 | |||
70 | public void RegisterAllCommands(Assembly assembly) | ||
71 | { | ||
72 | foreach (Type t in assembly.GetTypes()) | ||
73 | { | ||
74 | try | ||
75 | { | ||
76 | if (t.IsSubclassOf(typeof(Command))) | ||
77 | { | ||
78 | ConstructorInfo info = t.GetConstructor(new Type[] { typeof(TestClient) }); | ||
79 | Command command = (Command)info.Invoke(new object[] { this }); | ||
80 | RegisterCommand(command); | ||
81 | } | ||
82 | } | ||
83 | catch (Exception e) | ||
84 | { | ||
85 | Console.WriteLine(e.ToString()); | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | public void RegisterCommand(Command command) | ||
91 | { | ||
92 | command.Client = this; | ||
93 | if (!Commands.ContainsKey(command.Name.ToLower())) | ||
94 | { | ||
95 | Commands.Add(command.Name.ToLower(), command); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | //breaks up large responses to deal with the max IM size | ||
100 | private void SendResponseIM(SecondLife client, LLUUID fromAgentID, string data, LLUUID imSessionID) | ||
101 | { | ||
102 | for ( int i = 0 ; i < data.Length ; i += 1024 ) { | ||
103 | int y; | ||
104 | if ((i + 1023) > data.Length) | ||
105 | { | ||
106 | y = data.Length - i; | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | y = 1023; | ||
111 | } | ||
112 | string message = data.Substring(i, y); | ||
113 | client.Self.InstantMessage(fromAgentID, message, imSessionID); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | public void DoCommand(string cmd, LLUUID fromAgentID, LLUUID imSessionID) | ||
118 | { | ||
119 | string[] tokens = Parsing.ParseArguments(cmd); | ||
120 | |||
121 | if (tokens.Length == 0) | ||
122 | return; | ||
123 | |||
124 | string firstToken = tokens[0].ToLower(); | ||
125 | |||
126 | // "all balance" will send the balance command to all currently logged in bots | ||
127 | if (firstToken == "all" && tokens.Length > 1) | ||
128 | { | ||
129 | cmd = String.Empty; | ||
130 | |||
131 | // Reserialize all of the arguments except for "all" | ||
132 | for (int i = 1; i < tokens.Length; i++) | ||
133 | { | ||
134 | cmd += tokens[i] + " "; | ||
135 | } | ||
136 | |||
137 | ClientManager.DoCommandAll(cmd, fromAgentID, imSessionID); | ||
138 | |||
139 | return; | ||
140 | } | ||
141 | |||
142 | if (Commands.ContainsKey(firstToken)) | ||
143 | { | ||
144 | string[] args = new string[tokens.Length - 1]; | ||
145 | Array.Copy(tokens, 1, args, 0, args.Length); | ||
146 | string response = response = Commands[firstToken].Execute(args, fromAgentID); | ||
147 | |||
148 | if (response.Length > 0) | ||
149 | { | ||
150 | Console.WriteLine(response); | ||
151 | |||
152 | if (fromAgentID != null && Network.Connected) | ||
153 | { | ||
154 | // IMs don't like \r\n line endings, clean them up first | ||
155 | response = response.Replace("\r", ""); | ||
156 | SendResponseIM(this, fromAgentID, response, imSessionID); | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | private void updateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) | ||
163 | { | ||
164 | foreach (Command c in Commands.Values) | ||
165 | if (c.Active) | ||
166 | c.Think(); | ||
167 | } | ||
168 | |||
169 | private void AgentDataUpdateHandler(Packet packet, Simulator sim) | ||
170 | { | ||
171 | AgentDataUpdatePacket p = (AgentDataUpdatePacket)packet; | ||
172 | if (p.AgentData.AgentID == sim.Client.Network.AgentID) | ||
173 | { | ||
174 | Console.WriteLine("Got the group ID for " + sim.Client.ToString() + ", requesting group members..."); | ||
175 | GroupID = p.AgentData.ActiveGroupID; | ||
176 | |||
177 | sim.Client.Groups.BeginGetGroupMembers(GroupID); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | private void TestClient_OnLogMessage(string message, Helpers.LogLevel level) | ||
182 | { | ||
183 | Console.WriteLine("<" + this.ToString() + "> " + level.ToString() + ": " + message); | ||
184 | } | ||
185 | |||
186 | private void GroupMembersHandler(Dictionary<LLUUID, GroupMember> members) | ||
187 | { | ||
188 | Console.WriteLine("Got " + members.Count + " group members."); | ||
189 | GroupMembers = members; | ||
190 | } | ||
191 | |||
192 | private void Objects_OnObjectKilled(Simulator simulator, uint objectID) | ||
193 | { | ||
194 | lock (SimPrims) | ||
195 | { | ||
196 | if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(objectID)) | ||
197 | SimPrims[simulator].Remove(objectID); | ||
198 | } | ||
199 | |||
200 | lock (AvatarList) | ||
201 | { | ||
202 | if (AvatarList.ContainsKey(objectID)) | ||
203 | AvatarList.Remove(objectID); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | private void Objects_OnObjectUpdated(Simulator simulator, ObjectUpdate update, ulong regionHandle, ushort timeDilation) | ||
208 | { | ||
209 | regionX = (int)(regionHandle >> 32); | ||
210 | regionY = (int)(regionHandle & 0xFFFFFFFF); | ||
211 | |||
212 | if (update.Avatar) | ||
213 | { | ||
214 | lock (AvatarList) | ||
215 | { | ||
216 | // TODO: We really need a solid avatar and object tracker in Utilities to use here | ||
217 | if (AvatarList.ContainsKey(update.LocalID)) | ||
218 | { | ||
219 | AvatarList[update.LocalID].CollisionPlane = update.CollisionPlane; | ||
220 | AvatarList[update.LocalID].Position = update.Position; | ||
221 | AvatarList[update.LocalID].Velocity = update.Velocity; | ||
222 | AvatarList[update.LocalID].Acceleration = update.Acceleration; | ||
223 | AvatarList[update.LocalID].Rotation = update.Rotation; | ||
224 | AvatarList[update.LocalID].AngularVelocity = update.AngularVelocity; | ||
225 | AvatarList[update.LocalID].Textures = update.Textures; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | lock (SimPrims) | ||
232 | { | ||
233 | if (SimPrims.ContainsKey(simulator) && SimPrims[simulator].ContainsKey(update.LocalID)) | ||
234 | { | ||
235 | SimPrims[simulator][update.LocalID].Position = update.Position; | ||
236 | SimPrims[simulator][update.LocalID].Velocity = update.Velocity; | ||
237 | SimPrims[simulator][update.LocalID].Acceleration = update.Acceleration; | ||
238 | SimPrims[simulator][update.LocalID].Rotation = update.Rotation; | ||
239 | SimPrims[simulator][update.LocalID].AngularVelocity = update.AngularVelocity; | ||
240 | SimPrims[simulator][update.LocalID].Textures = update.Textures; | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | |||
246 | private void Objects_OnNewPrim(Simulator simulator, Primitive prim, ulong regionHandle, ushort timeDilation) | ||
247 | { | ||
248 | lock (SimPrims) | ||
249 | { | ||
250 | if (!SimPrims.ContainsKey(simulator)) | ||
251 | { | ||
252 | SimPrims[simulator] = new Dictionary<uint, Primitive>(10000); | ||
253 | } | ||
254 | |||
255 | SimPrims[simulator][prim.LocalID] = prim; | ||
256 | } | ||
257 | |||
258 | if ((prim.Flags & LLObject.ObjectFlags.CreateSelected) != 0 && OnPrimCreated != null) | ||
259 | { | ||
260 | OnPrimCreated(simulator, prim); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | private void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation) | ||
265 | { | ||
266 | lock (AvatarList) | ||
267 | { | ||
268 | AvatarList[avatar.LocalID] = avatar; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | private void AvatarAppearanceHandler(Packet packet, Simulator simulator) | ||
273 | { | ||
274 | AvatarAppearancePacket appearance = (AvatarAppearancePacket)packet; | ||
275 | |||
276 | lock (Appearances) Appearances[appearance.Sender.ID] = appearance; | ||
277 | } | ||
278 | |||
279 | private void Self_OnInstantMessage(LLUUID fromAgentID, string fromAgentName, LLUUID toAgentID, | ||
280 | uint parentEstateID, LLUUID regionID, LLVector3 position, MainAvatar.InstantMessageDialog dialog, | ||
281 | bool groupIM, LLUUID imSessionID, DateTime timestamp, string message, | ||
282 | MainAvatar.InstantMessageOnline offline, byte[] binaryBucket) | ||
283 | { | ||
284 | if (MasterKey != LLUUID.Zero) | ||
285 | { | ||
286 | if (fromAgentID != MasterKey) | ||
287 | { | ||
288 | // Received an IM from someone that is not the bot's master, ignore | ||
289 | Console.WriteLine("<IM>" + fromAgentName + " (not master): " + message + "@" + regionID.ToString() + ":" + position.ToString() ); | ||
290 | return; | ||
291 | } | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | if (GroupMembers != null && !GroupMembers.ContainsKey(fromAgentID)) | ||
296 | { | ||
297 | // Received an IM from someone outside the bot's group, ignore | ||
298 | Console.WriteLine("<IM>" + fromAgentName + " (not in group): " + message + "@" + regionID.ToString() + ":" + position.ToString()); | ||
299 | return; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | Console.WriteLine("<IM>" + fromAgentName + ": " + message); | ||
304 | |||
305 | if (dialog == MainAvatar.InstantMessageDialog.RequestTeleport) | ||
306 | { | ||
307 | Console.WriteLine("Accepting teleport lure."); | ||
308 | Self.TeleportLureRespond(fromAgentID, true); | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | if (dialog == MainAvatar.InstantMessageDialog.InventoryOffered) | ||
313 | { | ||
314 | Console.WriteLine("Accepting inventory offer."); | ||
315 | |||
316 | Self.InstantMessage(Self.FirstName + " " + Self.LastName, fromAgentID, String.Empty, | ||
317 | imSessionID, MainAvatar.InstantMessageDialog.InventoryAccepted, | ||
318 | MainAvatar.InstantMessageOnline.Offline, Self.Position, LLUUID.Zero, | ||
319 | Self.InventoryRootFolderUUID.GetBytes()); | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | DoCommand(message, fromAgentID, imSessionID); | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | } | ||