clockwerk-opensim-stable – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.Text; |
||
31 | using System.IO; |
||
32 | using System.Reflection; |
||
33 | using System.Threading; |
||
34 | using System.Timers; |
||
35 | using log4net; |
||
36 | using OpenMetaverse; |
||
37 | using OpenMetaverse.Assets; |
||
38 | using Nini.Config; |
||
39 | using OpenSim.Framework; |
||
40 | using OpenSim.Framework.Console; |
||
41 | using pCampBot.Interfaces; |
||
42 | using Timer = System.Timers.Timer; |
||
43 | using PermissionMask = OpenSim.Framework.PermissionMask; |
||
44 | |||
45 | namespace pCampBot |
||
46 | { |
||
47 | public enum ConnectionState |
||
48 | { |
||
49 | Disconnected, |
||
50 | Connecting, |
||
51 | Connected, |
||
52 | Disconnecting |
||
53 | } |
||
54 | |||
55 | public class Bot |
||
56 | { |
||
57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
58 | |||
59 | public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events |
||
60 | |||
61 | /// <summary> |
||
62 | /// Controls whether bots request textures for the object information they receive |
||
63 | /// </summary> |
||
64 | public bool RequestObjectTextures { get; set; } |
||
65 | |||
66 | /// <summary> |
||
67 | /// Bot manager. |
||
68 | /// </summary> |
||
69 | public BotManager Manager { get; private set; } |
||
70 | |||
71 | /// <summary> |
||
72 | /// Behaviours implemented by this bot. |
||
73 | /// </summary> |
||
74 | /// <remarks> |
||
75 | /// Indexed by abbreviated name. There can only be one instance of a particular behaviour. |
||
76 | /// Lock this structure before manipulating it. |
||
77 | /// </remarks> |
||
78 | public Dictionary<string, IBehaviour> Behaviours { get; private set; } |
||
79 | |||
80 | /// <summary> |
||
81 | /// Objects that the bot has discovered. |
||
82 | /// </summary> |
||
83 | /// <remarks> |
||
84 | /// Returns a list copy. Inserting new objects manually will have no effect. |
||
85 | /// </remarks> |
||
86 | public Dictionary<UUID, Primitive> Objects |
||
87 | { |
||
88 | get |
||
89 | { |
||
90 | lock (m_objects) |
||
91 | return new Dictionary<UUID, Primitive>(m_objects); |
||
92 | } |
||
93 | } |
||
94 | private Dictionary<UUID, Primitive> m_objects = new Dictionary<UUID, Primitive>(); |
||
95 | |||
96 | /// <summary> |
||
97 | /// Is this bot connected to the grid? |
||
98 | /// </summary> |
||
99 | public ConnectionState ConnectionState { get; private set; } |
||
100 | |||
101 | public List<Simulator> Simulators |
||
102 | { |
||
103 | get |
||
104 | { |
||
105 | lock (Client.Network.Simulators) |
||
106 | return new List<Simulator>(Client.Network.Simulators); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /// <summary> |
||
111 | /// The number of connections that this bot has to different simulators. |
||
112 | /// </summary> |
||
113 | /// <value>Includes both root and child connections.</value> |
||
114 | public int SimulatorsCount |
||
115 | { |
||
116 | get |
||
117 | { |
||
118 | lock (Client.Network.Simulators) |
||
119 | return Client.Network.Simulators.Count; |
||
120 | } |
||
121 | } |
||
122 | |||
123 | public string FirstName { get; private set; } |
||
124 | public string LastName { get; private set; } |
||
125 | public string Name { get; private set; } |
||
126 | public string Password { get; private set; } |
||
127 | public string LoginUri { get; private set; } |
||
128 | public string StartLocation { get; private set; } |
||
129 | |||
130 | public string saveDir; |
||
131 | public string wear; |
||
132 | |||
133 | public event AnEvent OnConnected; |
||
134 | public event AnEvent OnDisconnected; |
||
135 | |||
136 | /// <summary> |
||
137 | /// Keep a track of the continuously acting thread so that we can abort it. |
||
138 | /// </summary> |
||
139 | private Thread m_actionThread; |
||
140 | |||
141 | protected List<uint> objectIDs = new List<uint>(); |
||
142 | |||
143 | /// <summary> |
||
144 | /// Random number generator. |
||
145 | /// </summary> |
||
146 | public Random Random { get; private set; } |
||
147 | |||
148 | /// <summary> |
||
149 | /// New instance of a SecondLife client |
||
150 | /// </summary> |
||
151 | public GridClient Client { get; private set; } |
||
152 | |||
153 | /// <summary> |
||
154 | /// Constructor |
||
155 | /// </summary> |
||
156 | /// <param name="bm"></param> |
||
157 | /// <param name="behaviours">Behaviours for this bot to perform</param> |
||
158 | /// <param name="firstName"></param> |
||
159 | /// <param name="lastName"></param> |
||
160 | /// <param name="password"></param> |
||
161 | /// <param name="loginUri"></param> |
||
162 | /// <param name="behaviours"></param> |
||
163 | public Bot( |
||
164 | BotManager bm, List<IBehaviour> behaviours, |
||
165 | string firstName, string lastName, string password, string startLocation, string loginUri) |
||
166 | { |
||
167 | ConnectionState = ConnectionState.Disconnected; |
||
168 | |||
169 | Random = new Random(Environment.TickCount);// We do stuff randomly here |
||
170 | FirstName = firstName; |
||
171 | LastName = lastName; |
||
172 | Name = string.Format("{0} {1}", FirstName, LastName); |
||
173 | Password = password; |
||
174 | LoginUri = loginUri; |
||
175 | StartLocation = startLocation; |
||
176 | |||
177 | Manager = bm; |
||
178 | |||
179 | Behaviours = new Dictionary<string, IBehaviour>(); |
||
180 | foreach (IBehaviour behaviour in behaviours) |
||
181 | AddBehaviour(behaviour); |
||
182 | |||
183 | // Only calling for use as a template. |
||
184 | CreateLibOmvClient(); |
||
185 | } |
||
186 | |||
187 | public bool TryGetBehaviour(string abbreviatedName, out IBehaviour behaviour) |
||
188 | { |
||
189 | lock (Behaviours) |
||
190 | return Behaviours.TryGetValue(abbreviatedName, out behaviour); |
||
191 | } |
||
192 | |||
193 | public bool AddBehaviour(IBehaviour behaviour) |
||
194 | { |
||
195 | lock (Behaviours) |
||
196 | { |
||
197 | if (!Behaviours.ContainsKey(behaviour.AbbreviatedName)) |
||
198 | { |
||
199 | behaviour.Initialize(this); |
||
200 | Behaviours.Add(behaviour.AbbreviatedName, behaviour); |
||
201 | |||
202 | return true; |
||
203 | } |
||
204 | } |
||
205 | |||
206 | return false; |
||
207 | } |
||
208 | |||
209 | public bool RemoveBehaviour(string abbreviatedName) |
||
210 | { |
||
211 | lock (Behaviours) |
||
212 | { |
||
213 | IBehaviour behaviour; |
||
214 | |||
215 | if (!Behaviours.TryGetValue(abbreviatedName, out behaviour)) |
||
216 | return false; |
||
217 | |||
218 | behaviour.Close(); |
||
219 | Behaviours.Remove(abbreviatedName); |
||
220 | |||
221 | return true; |
||
222 | } |
||
223 | } |
||
224 | |||
225 | private void CreateLibOmvClient() |
||
226 | { |
||
227 | GridClient newClient = new GridClient(); |
||
228 | |||
229 | if (Client != null) |
||
230 | { |
||
231 | newClient.Settings.LOGIN_SERVER = Client.Settings.LOGIN_SERVER; |
||
232 | newClient.Settings.ALWAYS_DECODE_OBJECTS = Client.Settings.ALWAYS_DECODE_OBJECTS; |
||
233 | newClient.Settings.AVATAR_TRACKING = Client.Settings.AVATAR_TRACKING; |
||
234 | newClient.Settings.OBJECT_TRACKING = Client.Settings.OBJECT_TRACKING; |
||
235 | newClient.Settings.SEND_AGENT_THROTTLE = Client.Settings.SEND_AGENT_THROTTLE; |
||
236 | newClient.Settings.SEND_AGENT_UPDATES = Client.Settings.SEND_AGENT_UPDATES; |
||
237 | newClient.Settings.SEND_PINGS = Client.Settings.SEND_PINGS; |
||
238 | newClient.Settings.STORE_LAND_PATCHES = Client.Settings.STORE_LAND_PATCHES; |
||
239 | newClient.Settings.USE_ASSET_CACHE = Client.Settings.USE_ASSET_CACHE; |
||
240 | newClient.Settings.MULTIPLE_SIMS = Client.Settings.MULTIPLE_SIMS; |
||
241 | newClient.Throttle.Asset = Client.Throttle.Asset; |
||
242 | newClient.Throttle.Land = Client.Throttle.Land; |
||
243 | newClient.Throttle.Task = Client.Throttle.Task; |
||
244 | newClient.Throttle.Texture = Client.Throttle.Texture; |
||
245 | newClient.Throttle.Wind = Client.Throttle.Wind; |
||
246 | newClient.Throttle.Total = Client.Throttle.Total; |
||
247 | } |
||
248 | else |
||
249 | { |
||
250 | newClient.Settings.LOGIN_SERVER = LoginUri; |
||
251 | newClient.Settings.ALWAYS_DECODE_OBJECTS = false; |
||
252 | newClient.Settings.AVATAR_TRACKING = false; |
||
253 | newClient.Settings.OBJECT_TRACKING = false; |
||
254 | newClient.Settings.SEND_AGENT_THROTTLE = true; |
||
255 | newClient.Settings.SEND_PINGS = true; |
||
256 | newClient.Settings.STORE_LAND_PATCHES = false; |
||
257 | newClient.Settings.USE_ASSET_CACHE = false; |
||
258 | newClient.Settings.MULTIPLE_SIMS = true; |
||
259 | newClient.Throttle.Asset = 100000; |
||
260 | newClient.Throttle.Land = 100000; |
||
261 | newClient.Throttle.Task = 100000; |
||
262 | newClient.Throttle.Texture = 100000; |
||
263 | newClient.Throttle.Wind = 100000; |
||
264 | newClient.Throttle.Total = 400000; |
||
265 | } |
||
266 | |||
267 | newClient.Network.LoginProgress += this.Network_LoginProgress; |
||
268 | newClient.Network.SimConnected += this.Network_SimConnected; |
||
269 | newClient.Network.Disconnected += this.Network_OnDisconnected; |
||
270 | newClient.Objects.ObjectUpdate += Objects_NewPrim; |
||
271 | |||
272 | Client = newClient; |
||
273 | } |
||
274 | |||
275 | //We do our actions here. This is where one would |
||
276 | //add additional steps and/or things the bot should do |
||
277 | private void Action() |
||
278 | { |
||
279 | while (ConnectionState != ConnectionState.Disconnecting) |
||
280 | { |
||
281 | lock (Behaviours) |
||
282 | { |
||
283 | foreach (IBehaviour behaviour in Behaviours.Values) |
||
284 | { |
||
285 | // Thread.Sleep(Random.Next(3000, 10000)); |
||
286 | |||
287 | // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); |
||
288 | behaviour.Action(); |
||
289 | } |
||
290 | } |
||
291 | |||
292 | // XXX: This is a really shitty way of yielding so that behaviours can be added/removed |
||
293 | Thread.Sleep(100); |
||
294 | } |
||
295 | |||
296 | lock (Behaviours) |
||
297 | foreach (IBehaviour b in Behaviours.Values) |
||
298 | b.Close(); |
||
299 | } |
||
300 | |||
301 | /// <summary> |
||
302 | /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. |
||
303 | /// </summary> |
||
304 | public void Disconnect() |
||
305 | { |
||
306 | ConnectionState = ConnectionState.Disconnecting; |
||
307 | |||
308 | // if (m_actionThread != null) |
||
309 | // m_actionThread.Abort(); |
||
310 | |||
311 | Client.Network.Logout(); |
||
312 | } |
||
313 | |||
314 | public void Connect() |
||
315 | { |
||
316 | Thread connectThread = new Thread(ConnectInternal); |
||
317 | connectThread.Name = Name; |
||
318 | connectThread.IsBackground = true; |
||
319 | |||
320 | connectThread.Start(); |
||
321 | } |
||
322 | |||
323 | /// <summary> |
||
324 | /// This is the bot startup loop. |
||
325 | /// </summary> |
||
326 | private void ConnectInternal() |
||
327 | { |
||
328 | ConnectionState = ConnectionState.Connecting; |
||
329 | |||
330 | // Current create a new client on each connect. libomv doesn't seem to process new sim |
||
331 | // information (e.g. EstablishAgentCommunication events) if connecting after a disceonnect with the same |
||
332 | // client |
||
333 | CreateLibOmvClient(); |
||
334 | |||
335 | if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name")) |
||
336 | { |
||
337 | ConnectionState = ConnectionState.Connected; |
||
338 | |||
339 | Thread.Sleep(Random.Next(1000, 10000)); |
||
340 | m_actionThread = new Thread(Action); |
||
341 | m_actionThread.Start(); |
||
342 | |||
343 | // OnConnected(this, EventType.CONNECTED); |
||
344 | if (wear == "save") |
||
345 | { |
||
346 | Client.Appearance.SetPreviousAppearance(); |
||
347 | SaveDefaultAppearance(); |
||
348 | } |
||
349 | else if (wear != "no") |
||
350 | { |
||
351 | MakeDefaultAppearance(wear); |
||
352 | } |
||
353 | |||
354 | // Extract nearby region information. |
||
355 | Client.Grid.GridRegion += Manager.Grid_GridRegion; |
||
356 | uint xUint, yUint; |
||
357 | Utils.LongToUInts(Client.Network.CurrentSim.Handle, out xUint, out yUint); |
||
358 | ushort minX, minY, maxX, maxY; |
||
359 | minX = (ushort)Math.Min(0, xUint - 5); |
||
360 | minY = (ushort)Math.Min(0, yUint - 5); |
||
361 | maxX = (ushort)(xUint + 5); |
||
362 | maxY = (ushort)(yUint + 5); |
||
363 | Client.Grid.RequestMapBlocks(GridLayerType.Terrain, minX, minY, maxX, maxY, false); |
||
364 | } |
||
365 | else |
||
366 | { |
||
367 | ConnectionState = ConnectionState.Disconnected; |
||
368 | |||
369 | m_log.ErrorFormat( |
||
370 | "{0} {1} cannot login: {2}", FirstName, LastName, Client.Network.LoginMessage); |
||
371 | |||
372 | if (OnDisconnected != null) |
||
373 | { |
||
374 | OnDisconnected(this, EventType.DISCONNECTED); |
||
375 | } |
||
376 | } |
||
377 | } |
||
378 | |||
379 | /// <summary> |
||
380 | /// Sit this bot on the ground. |
||
381 | /// </summary> |
||
382 | public void SitOnGround() |
||
383 | { |
||
384 | if (ConnectionState == ConnectionState.Connected) |
||
385 | Client.Self.SitOnGround(); |
||
386 | } |
||
387 | |||
388 | /// <summary> |
||
389 | /// Stand this bot |
||
390 | /// </summary> |
||
391 | public void Stand() |
||
392 | { |
||
393 | if (ConnectionState == ConnectionState.Connected) |
||
394 | { |
||
395 | // Unlike sit on ground, here libomv checks whether we have SEND_AGENT_UPDATES enabled. |
||
396 | bool prevUpdatesSetting = Client.Settings.SEND_AGENT_UPDATES; |
||
397 | Client.Settings.SEND_AGENT_UPDATES = true; |
||
398 | Client.Self.Stand(); |
||
399 | Client.Settings.SEND_AGENT_UPDATES = prevUpdatesSetting; |
||
400 | } |
||
401 | } |
||
402 | |||
403 | public void SaveDefaultAppearance() |
||
404 | { |
||
405 | saveDir = "MyAppearance/" + FirstName + "_" + LastName; |
||
406 | if (!Directory.Exists(saveDir)) |
||
407 | { |
||
408 | Directory.CreateDirectory(saveDir); |
||
409 | } |
||
410 | |||
411 | Array wtypes = Enum.GetValues(typeof(WearableType)); |
||
412 | foreach (WearableType wtype in wtypes) |
||
413 | { |
||
414 | UUID wearable = Client.Appearance.GetWearableAsset(wtype); |
||
415 | if (wearable != UUID.Zero) |
||
416 | { |
||
417 | Client.Assets.RequestAsset(wearable, AssetType.Clothing, false, Asset_ReceivedCallback); |
||
418 | Client.Assets.RequestAsset(wearable, AssetType.Bodypart, false, Asset_ReceivedCallback); |
||
419 | } |
||
420 | } |
||
421 | } |
||
422 | |||
423 | public void SaveAsset(AssetWearable asset) |
||
424 | { |
||
425 | if (asset != null) |
||
426 | { |
||
427 | try |
||
428 | { |
||
429 | if (asset.Decode()) |
||
430 | { |
||
431 | File.WriteAllBytes(Path.Combine(saveDir, String.Format("{1}.{0}", |
||
432 | asset.AssetType.ToString().ToLower(), |
||
433 | asset.WearableType)), asset.AssetData); |
||
434 | } |
||
435 | else |
||
436 | { |
||
437 | m_log.WarnFormat("Failed to decode {0} asset {1}", asset.AssetType, asset.AssetID); |
||
438 | } |
||
439 | } |
||
440 | catch (Exception e) |
||
441 | { |
||
442 | m_log.ErrorFormat("Exception: {0}{1}", e.Message, e.StackTrace); |
||
443 | } |
||
444 | } |
||
445 | } |
||
446 | |||
447 | public WearableType GetWearableType(string path) |
||
448 | { |
||
449 | string type = ((((path.Split('/'))[2]).Split('.'))[0]).Trim(); |
||
450 | switch (type) |
||
451 | { |
||
452 | case "Eyes": |
||
453 | return WearableType.Eyes; |
||
454 | case "Hair": |
||
455 | return WearableType.Hair; |
||
456 | case "Pants": |
||
457 | return WearableType.Pants; |
||
458 | case "Shape": |
||
459 | return WearableType.Shape; |
||
460 | case "Shirt": |
||
461 | return WearableType.Shirt; |
||
462 | case "Skin": |
||
463 | return WearableType.Skin; |
||
464 | default: |
||
465 | return WearableType.Shape; |
||
466 | } |
||
467 | } |
||
468 | |||
469 | public void MakeDefaultAppearance(string wear) |
||
470 | { |
||
471 | try |
||
472 | { |
||
473 | if (wear == "yes") |
||
474 | { |
||
475 | //TODO: Implement random outfit picking |
||
476 | m_log.DebugFormat("Picks a random outfit. Not yet implemented."); |
||
477 | } |
||
478 | else if (wear != "save") |
||
479 | saveDir = "MyAppearance/" + wear; |
||
480 | saveDir = saveDir + "/"; |
||
481 | |||
482 | string[] clothing = Directory.GetFiles(saveDir, "*.clothing", SearchOption.TopDirectoryOnly); |
||
483 | string[] bodyparts = Directory.GetFiles(saveDir, "*.bodypart", SearchOption.TopDirectoryOnly); |
||
484 | InventoryFolder clothfolder = FindClothingFolder(); |
||
485 | UUID transid = UUID.Random(); |
||
486 | List<InventoryBase> listwearables = new List<InventoryBase>(); |
||
487 | |||
488 | for (int i = 0; i < clothing.Length; i++) |
||
489 | { |
||
490 | UUID assetID = UUID.Random(); |
||
491 | AssetClothing asset = new AssetClothing(assetID, File.ReadAllBytes(clothing[i])); |
||
492 | asset.Decode(); |
||
493 | asset.Owner = Client.Self.AgentID; |
||
494 | asset.WearableType = GetWearableType(clothing[i]); |
||
495 | asset.Encode(); |
||
496 | transid = Client.Assets.RequestUpload(asset,true); |
||
497 | Client.Inventory.RequestCreateItem(clothfolder.UUID, "MyClothing" + i.ToString(), "MyClothing", AssetType.Clothing, |
||
498 | transid, InventoryType.Wearable, asset.WearableType, (OpenMetaverse.PermissionMask)PermissionMask.All, delegate(bool success, InventoryItem item) |
||
499 | { |
||
500 | if (success) |
||
501 | { |
||
502 | listwearables.Add(item); |
||
503 | } |
||
504 | else |
||
505 | { |
||
506 | m_log.WarnFormat("Failed to create item {0}", item.Name); |
||
507 | } |
||
508 | } |
||
509 | ); |
||
510 | } |
||
511 | |||
512 | for (int i = 0; i < bodyparts.Length; i++) |
||
513 | { |
||
514 | UUID assetID = UUID.Random(); |
||
515 | AssetBodypart asset = new AssetBodypart(assetID, File.ReadAllBytes(bodyparts[i])); |
||
516 | asset.Decode(); |
||
517 | asset.Owner = Client.Self.AgentID; |
||
518 | asset.WearableType = GetWearableType(bodyparts[i]); |
||
519 | asset.Encode(); |
||
520 | transid = Client.Assets.RequestUpload(asset,true); |
||
521 | Client.Inventory.RequestCreateItem(clothfolder.UUID, "MyBodyPart" + i.ToString(), "MyBodyPart", AssetType.Bodypart, |
||
522 | transid, InventoryType.Wearable, asset.WearableType, (OpenMetaverse.PermissionMask)PermissionMask.All, delegate(bool success, InventoryItem item) |
||
523 | { |
||
524 | if (success) |
||
525 | { |
||
526 | listwearables.Add(item); |
||
527 | } |
||
528 | else |
||
529 | { |
||
530 | m_log.WarnFormat("Failed to create item {0}", item.Name); |
||
531 | } |
||
532 | } |
||
533 | ); |
||
534 | } |
||
535 | |||
536 | Thread.Sleep(1000); |
||
537 | |||
538 | if (listwearables == null || listwearables.Count == 0) |
||
539 | { |
||
540 | m_log.DebugFormat("Nothing to send on this folder!"); |
||
541 | } |
||
542 | else |
||
543 | { |
||
544 | m_log.DebugFormat("Sending {0} wearables...", listwearables.Count); |
||
545 | Client.Appearance.WearOutfit(listwearables, false); |
||
546 | } |
||
547 | } |
||
548 | catch (Exception ex) |
||
549 | { |
||
550 | Console.WriteLine(ex.ToString()); |
||
551 | } |
||
552 | } |
||
553 | |||
554 | public InventoryFolder FindClothingFolder() |
||
555 | { |
||
556 | UUID rootfolder = Client.Inventory.Store.RootFolder.UUID; |
||
557 | List<InventoryBase> listfolders = Client.Inventory.Store.GetContents(rootfolder); |
||
558 | InventoryFolder clothfolder = new InventoryFolder(UUID.Random()); |
||
559 | foreach (InventoryBase folder in listfolders) |
||
560 | { |
||
561 | if (folder.Name == "Clothing") |
||
562 | { |
||
563 | clothfolder = (InventoryFolder)folder; |
||
564 | break; |
||
565 | } |
||
566 | } |
||
567 | return clothfolder; |
||
568 | } |
||
569 | |||
570 | public void Network_LoginProgress(object sender, LoginProgressEventArgs args) |
||
571 | { |
||
572 | m_log.DebugFormat("[BOT]: Bot {0} {1} in Network_LoginProcess", Name, args.Status); |
||
573 | |||
574 | if (args.Status == LoginStatus.Success) |
||
575 | { |
||
576 | if (OnConnected != null) |
||
577 | { |
||
578 | OnConnected(this, EventType.CONNECTED); |
||
579 | } |
||
580 | } |
||
581 | } |
||
582 | |||
583 | public void Network_SimConnected(object sender, SimConnectedEventArgs args) |
||
584 | { |
||
585 | m_log.DebugFormat( |
||
586 | "[BOT]: Bot {0} connected to {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint); |
||
587 | } |
||
588 | |||
589 | public void Network_OnDisconnected(object sender, DisconnectedEventArgs args) |
||
590 | { |
||
591 | ConnectionState = ConnectionState.Disconnected; |
||
592 | |||
593 | m_log.DebugFormat( |
||
594 | "[BOT]: Bot {0} disconnected reason {1}, message {2}", Name, args.Reason, args.Message); |
||
595 | |||
596 | // m_log.ErrorFormat("Fired Network_OnDisconnected"); |
||
597 | |||
598 | // if ( |
||
599 | // (args.Reason == NetworkManager.DisconnectType.SimShutdown |
||
600 | // || args.Reason == NetworkManager.DisconnectType.NetworkTimeout) |
||
601 | // && OnDisconnected != null) |
||
602 | |||
603 | |||
604 | |||
605 | if ( |
||
606 | (args.Reason == NetworkManager.DisconnectType.ClientInitiated |
||
607 | || args.Reason == NetworkManager.DisconnectType.ServerInitiated |
||
608 | || args.Reason == NetworkManager.DisconnectType.NetworkTimeout) |
||
609 | && OnDisconnected != null) |
||
610 | // if (OnDisconnected != null) |
||
611 | { |
||
612 | OnDisconnected(this, EventType.DISCONNECTED); |
||
613 | } |
||
614 | } |
||
615 | |||
616 | public void Objects_NewPrim(object sender, PrimEventArgs args) |
||
617 | { |
||
618 | if (!RequestObjectTextures) |
||
619 | return; |
||
620 | |||
621 | Primitive prim = args.Prim; |
||
622 | |||
623 | if (prim != null) |
||
624 | { |
||
625 | lock (m_objects) |
||
626 | m_objects[prim.ID] = prim; |
||
627 | |||
628 | if (prim.Textures != null) |
||
629 | { |
||
630 | if (prim.Textures.DefaultTexture.TextureID != UUID.Zero) |
||
631 | { |
||
632 | GetTexture(prim.Textures.DefaultTexture.TextureID); |
||
633 | } |
||
634 | |||
635 | for (int i = 0; i < prim.Textures.FaceTextures.Length; i++) |
||
636 | { |
||
637 | Primitive.TextureEntryFace face = prim.Textures.FaceTextures[i]; |
||
638 | |||
639 | if (face != null) |
||
640 | { |
||
641 | UUID textureID = prim.Textures.FaceTextures[i].TextureID; |
||
642 | |||
643 | if (textureID != UUID.Zero) |
||
644 | GetTexture(textureID); |
||
645 | } |
||
646 | } |
||
647 | } |
||
648 | |||
649 | if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero) |
||
650 | GetTexture(prim.Sculpt.SculptTexture); |
||
651 | } |
||
652 | } |
||
653 | |||
654 | private void GetTexture(UUID textureID) |
||
655 | { |
||
656 | lock (Manager.AssetsReceived) |
||
657 | { |
||
658 | // Don't request assets more than once. |
||
659 | if (Manager.AssetsReceived.ContainsKey(textureID)) |
||
660 | return; |
||
661 | |||
662 | Manager.AssetsReceived[textureID] = false; |
||
663 | Client.Assets.RequestImage(textureID, ImageType.Normal, Asset_TextureCallback_Texture); |
||
664 | } |
||
665 | } |
||
666 | |||
667 | public void Asset_TextureCallback_Texture(TextureRequestState state, AssetTexture assetTexture) |
||
668 | { |
||
669 | //TODO: Implement texture saving and applying |
||
670 | } |
||
671 | |||
672 | public void Asset_ReceivedCallback(AssetDownload transfer, Asset asset) |
||
673 | { |
||
674 | lock (Manager.AssetsReceived) |
||
675 | Manager.AssetsReceived[asset.AssetID] = true; |
||
676 | |||
677 | // if (wear == "save") |
||
678 | // { |
||
679 | // SaveAsset((AssetWearable) asset); |
||
680 | // } |
||
681 | } |
||
682 | } |
||
683 | } |