PhysicsBot.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. using System.IO;
  31. using System.Threading;
  32. using System.Timers;
  33. using OpenMetaverse;
  34. using OpenMetaverse.Assets;
  35. using Nini.Config;
  36. using OpenSim.Framework;
  37. using OpenSim.Framework.Console;
  38. using Timer=System.Timers.Timer;
  39. namespace pCampBot
  40. {
  41. public class PhysicsBot
  42. {
  43. public delegate void AnEvent(PhysicsBot callbot, EventType someevent); // event delegate for bot events
  44. public IConfig startupConfig; // bot config, passed from BotManager
  45. public string firstname;
  46. public string lastname;
  47. public string password;
  48. public string loginURI;
  49. public string saveDir;
  50. public string wear;
  51. public event AnEvent OnConnected;
  52. public event AnEvent OnDisconnected;
  53. protected Timer m_action; // Action Timer
  54. protected List<uint> objectIDs = new List<uint>();
  55. protected Random somthing = new Random(Environment.TickCount);// We do stuff randomly here
  56. //New instance of a SecondLife client
  57. public GridClient client = new GridClient();
  58. protected string[] talkarray;
  59. /// <summary>
  60. ///
  61. /// </summary>
  62. /// <param name="bsconfig">nini config for the bot</param>
  63. public PhysicsBot(IConfig bsconfig)
  64. {
  65. startupConfig = bsconfig;
  66. readconfig();
  67. talkarray = readexcuses();
  68. }
  69. //We do our actions here. This is where one would
  70. //add additional steps and/or things the bot should do
  71. void m_action_Elapsed(object sender, ElapsedEventArgs e)
  72. {
  73. while (true)
  74. {
  75. int walkorrun = somthing.Next(4); // Randomize between walking and running. The greater this number,
  76. // the greater the bot's chances to walk instead of run.
  77. client.Self.Jump(false);
  78. if (walkorrun == 0)
  79. {
  80. client.Self.Movement.AlwaysRun = true;
  81. }
  82. else
  83. {
  84. client.Self.Movement.AlwaysRun = false;
  85. }
  86. // TODO: unused: Vector3 pos = client.Self.SimPosition;
  87. Vector3 newpos = new Vector3(somthing.Next(255), somthing.Next(255), somthing.Next(255));
  88. client.Self.Movement.TurnToward(newpos);
  89. client.Self.Movement.AtPos = true;
  90. Thread.Sleep(somthing.Next(3000,13000));
  91. client.Self.Movement.AtPos = false;
  92. client.Self.Jump(true);
  93. string randomf = talkarray[somthing.Next(talkarray.Length)];
  94. if (talkarray.Length > 1 && randomf.Length > 1)
  95. client.Self.Chat(randomf, 0, ChatType.Normal);
  96. Thread.Sleep(somthing.Next(1000, 10000));
  97. }
  98. }
  99. /// <summary>
  100. /// Read the Nini config and initialize
  101. /// </summary>
  102. public void readconfig()
  103. {
  104. firstname = startupConfig.GetString("firstname", "random");
  105. lastname = startupConfig.GetString("lastname", "random");
  106. password = startupConfig.GetString("password", "12345");
  107. loginURI = startupConfig.GetString("loginuri");
  108. wear = startupConfig.GetString("wear","no");
  109. }
  110. /// <summary>
  111. /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes.
  112. /// </summary>
  113. public void shutdown()
  114. {
  115. client.Network.Logout();
  116. }
  117. /// <summary>
  118. /// This is the bot startup loop.
  119. /// </summary>
  120. public void startup()
  121. {
  122. client.Settings.LOGIN_SERVER = loginURI;
  123. client.Settings.ALWAYS_DECODE_OBJECTS = false;
  124. client.Settings.AVATAR_TRACKING = false;
  125. client.Settings.OBJECT_TRACKING = false;
  126. client.Settings.SEND_AGENT_THROTTLE = true;
  127. client.Settings.SEND_PINGS = true;
  128. client.Settings.STORE_LAND_PATCHES = false;
  129. client.Settings.USE_ASSET_CACHE = false;
  130. client.Settings.MULTIPLE_SIMS = true;
  131. client.Throttle.Asset = 100000;
  132. client.Throttle.Land = 100000;
  133. client.Throttle.Task = 100000;
  134. client.Throttle.Texture = 100000;
  135. client.Throttle.Wind = 100000;
  136. client.Throttle.Total = 400000;
  137. client.Network.LoginProgress += this.Network_LoginProgress;
  138. client.Network.SimConnected += this.Network_SimConnected;
  139. client.Network.Disconnected += this.Network_OnDisconnected;
  140. client.Objects.ObjectUpdate += Objects_NewPrim;
  141. //client.Assets.OnAssetReceived += Asset_ReceivedCallback;
  142. if (client.Network.Login(firstname, lastname, password, "pCampBot", "Your name"))
  143. {
  144. if (OnConnected != null)
  145. {
  146. m_action = new Timer(somthing.Next(1000, 10000));
  147. m_action.Enabled = true;
  148. m_action.AutoReset = false;
  149. m_action.Elapsed += new ElapsedEventHandler(m_action_Elapsed);
  150. m_action.Start();
  151. OnConnected(this, EventType.CONNECTED);
  152. if (wear == "save")
  153. {
  154. client.Appearance.SetPreviousAppearance();
  155. SaveDefaultAppearance();
  156. }
  157. else if (wear != "no")
  158. {
  159. MakeDefaultAppearance(wear);
  160. }
  161. client.Self.Jump(true);
  162. }
  163. }
  164. else
  165. {
  166. MainConsole.Instance.Output(firstname + " " + lastname + " Can't login: " + client.Network.LoginMessage);
  167. if (OnDisconnected != null)
  168. {
  169. OnDisconnected(this, EventType.DISCONNECTED);
  170. }
  171. }
  172. }
  173. public void SaveDefaultAppearance()
  174. {
  175. saveDir = "MyAppearance/" + firstname + "_" + lastname;
  176. if (!Directory.Exists(saveDir))
  177. {
  178. Directory.CreateDirectory(saveDir);
  179. }
  180. Array wtypes = Enum.GetValues(typeof(WearableType));
  181. foreach (WearableType wtype in wtypes)
  182. {
  183. UUID wearable = client.Appearance.GetWearableAsset(wtype);
  184. if (wearable != UUID.Zero)
  185. {
  186. client.Assets.RequestAsset(wearable, AssetType.Clothing, false, Asset_ReceivedCallback);
  187. client.Assets.RequestAsset(wearable, AssetType.Bodypart, false, Asset_ReceivedCallback);
  188. }
  189. }
  190. }
  191. public void SaveAsset(AssetWearable asset)
  192. {
  193. if (asset != null)
  194. {
  195. try
  196. {
  197. if (asset.Decode())
  198. {
  199. File.WriteAllBytes(Path.Combine(saveDir, String.Format("{1}.{0}",
  200. asset.AssetType.ToString().ToLower(),
  201. asset.WearableType)), asset.AssetData);
  202. }
  203. else
  204. {
  205. MainConsole.Instance.Output(String.Format("Failed to decode {0} asset {1}", asset.AssetType, asset.AssetID));
  206. }
  207. }
  208. catch (Exception e)
  209. {
  210. MainConsole.Instance.Output(String.Format("Exception: {0}",e.ToString()));
  211. }
  212. }
  213. }
  214. public WearableType GetWearableType(string path)
  215. {
  216. string type = ((((path.Split('/'))[2]).Split('.'))[0]).Trim();
  217. switch (type)
  218. {
  219. case "Eyes":
  220. return WearableType.Eyes;
  221. case "Hair":
  222. return WearableType.Hair;
  223. case "Pants":
  224. return WearableType.Pants;
  225. case "Shape":
  226. return WearableType.Shape;
  227. case "Shirt":
  228. return WearableType.Shirt;
  229. case "Skin":
  230. return WearableType.Skin;
  231. default:
  232. return WearableType.Shape;
  233. }
  234. }
  235. public void MakeDefaultAppearance(string wear)
  236. {
  237. try
  238. {
  239. if (wear == "yes")
  240. {
  241. //TODO: Implement random outfit picking
  242. MainConsole.Instance.Output("Picks a random outfit. Not yet implemented.");
  243. }
  244. else if (wear != "save")
  245. saveDir = "MyAppearance/" + wear;
  246. saveDir = saveDir + "/";
  247. string[] clothing = Directory.GetFiles(saveDir, "*.clothing", SearchOption.TopDirectoryOnly);
  248. string[] bodyparts = Directory.GetFiles(saveDir, "*.bodypart", SearchOption.TopDirectoryOnly);
  249. InventoryFolder clothfolder = FindClothingFolder();
  250. UUID transid = UUID.Random();
  251. List<InventoryBase> listwearables = new List<InventoryBase>();
  252. for (int i = 0; i < clothing.Length; i++)
  253. {
  254. UUID assetID = UUID.Random();
  255. AssetClothing asset = new AssetClothing(assetID, File.ReadAllBytes(clothing[i]));
  256. asset.Decode();
  257. asset.Owner = client.Self.AgentID;
  258. asset.WearableType = GetWearableType(clothing[i]);
  259. asset.Encode();
  260. transid = client.Assets.RequestUpload(asset,true);
  261. client.Inventory.RequestCreateItem(clothfolder.UUID, "MyClothing" + i.ToString(), "MyClothing", AssetType.Clothing,
  262. transid, InventoryType.Wearable, asset.WearableType, PermissionMask.All, delegate(bool success, InventoryItem item)
  263. {
  264. if (success)
  265. {
  266. listwearables.Add(item);
  267. }
  268. else
  269. MainConsole.Instance.Output(String.Format("Failed to create item {0}",item.Name));
  270. }
  271. );
  272. }
  273. for (int i = 0; i < bodyparts.Length; i++)
  274. {
  275. UUID assetID = UUID.Random();
  276. AssetBodypart asset = new AssetBodypart(assetID, File.ReadAllBytes(bodyparts[i]));
  277. asset.Decode();
  278. asset.Owner = client.Self.AgentID;
  279. asset.WearableType = GetWearableType(bodyparts[i]);
  280. asset.Encode();
  281. transid = client.Assets.RequestUpload(asset,true);
  282. client.Inventory.RequestCreateItem(clothfolder.UUID, "MyBodyPart" + i.ToString(), "MyBodyPart", AssetType.Bodypart,
  283. transid, InventoryType.Wearable, asset.WearableType, PermissionMask.All, delegate(bool success, InventoryItem item)
  284. {
  285. if (success)
  286. {
  287. listwearables.Add(item);
  288. }
  289. else
  290. MainConsole.Instance.Output(String.Format("Failed to create item {0}",item.Name));
  291. }
  292. );
  293. }
  294. Thread.Sleep(1000);
  295. if (listwearables == null || listwearables.Count == 0)
  296. MainConsole.Instance.Output("Nothing to send on this folder!");
  297. else
  298. {
  299. MainConsole.Instance.Output(String.Format("Sending {0} wearables...",listwearables.Count));
  300. client.Appearance.WearOutfit(listwearables, false);
  301. }
  302. }
  303. catch (Exception ex)
  304. {
  305. Console.WriteLine(ex.ToString());
  306. }
  307. }
  308. public InventoryFolder FindClothingFolder()
  309. {
  310. UUID rootfolder = client.Inventory.Store.RootFolder.UUID;
  311. List<InventoryBase> listfolders = client.Inventory.Store.GetContents(rootfolder);
  312. InventoryFolder clothfolder = new InventoryFolder(UUID.Random());
  313. foreach (InventoryBase folder in listfolders)
  314. {
  315. if (folder.Name == "Clothing")
  316. {
  317. clothfolder = (InventoryFolder)folder;
  318. break;
  319. }
  320. }
  321. return clothfolder;
  322. }
  323. public void Network_LoginProgress(object sender, LoginProgressEventArgs args)
  324. {
  325. if (args.Status == LoginStatus.Success)
  326. {
  327. if (OnConnected != null)
  328. {
  329. OnConnected(this, EventType.CONNECTED);
  330. }
  331. }
  332. }
  333. public void Network_SimConnected(object sender, SimConnectedEventArgs args)
  334. {
  335. }
  336. public void Network_OnDisconnected(object sender, DisconnectedEventArgs args)
  337. {
  338. if (OnDisconnected != null)
  339. {
  340. OnDisconnected(this, EventType.DISCONNECTED);
  341. }
  342. }
  343. public void Objects_NewPrim(object sender, PrimEventArgs args)
  344. {
  345. Primitive prim = args.Prim;
  346. if (prim != null)
  347. {
  348. if (prim.Textures != null)
  349. {
  350. if (prim.Textures.DefaultTexture.TextureID != UUID.Zero)
  351. {
  352. client.Assets.RequestImage(prim.Textures.DefaultTexture.TextureID, ImageType.Normal, Asset_TextureCallback_Texture);
  353. }
  354. for (int i = 0; i < prim.Textures.FaceTextures.Length; i++)
  355. {
  356. if (prim.Textures.FaceTextures[i] != null)
  357. {
  358. if (prim.Textures.FaceTextures[i].TextureID != UUID.Zero)
  359. {
  360. client.Assets.RequestImage(prim.Textures.FaceTextures[i].TextureID, ImageType.Normal, Asset_TextureCallback_Texture);
  361. }
  362. }
  363. }
  364. }
  365. if (prim.Sculpt.SculptTexture != UUID.Zero)
  366. {
  367. client.Assets.RequestImage(prim.Sculpt.SculptTexture, ImageType.Normal, Asset_TextureCallback_Texture);
  368. }
  369. }
  370. }
  371. public void Asset_TextureCallback_Texture(TextureRequestState state, AssetTexture assetTexture)
  372. {
  373. //TODO: Implement texture saving and applying
  374. }
  375. public void Asset_ReceivedCallback(AssetDownload transfer,Asset asset)
  376. {
  377. if (wear == "save")
  378. {
  379. SaveAsset((AssetWearable) asset);
  380. }
  381. }
  382. public string[] readexcuses()
  383. {
  384. string allexcuses = "";
  385. string file = Path.Combine(Util.configDir(), "pCampBotSentences.txt");
  386. if (File.Exists(file))
  387. {
  388. StreamReader csr = File.OpenText(file);
  389. allexcuses = csr.ReadToEnd();
  390. csr.Close();
  391. }
  392. return allexcuses.Split(Environment.NewLine.ToCharArray());
  393. }
  394. }
  395. }