/Aurora/BotManager/BotManager.cs

https://bitbucket.org/VirtualReality/software-testing · C# · 517 lines · 364 code · 55 blank · 98 comment · 61 complexity · 9472a1739edf3caf5932489d228591c8 MD5 · raw file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.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 Aurora-Sim 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 Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.PresenceInfo;
  32. using Aurora.Framework.SceneInfo;
  33. using Aurora.Framework.SceneInfo.Entities;
  34. using Aurora.Framework.Services.ClassHelpers.Inventory;
  35. using Aurora.Framework.Utilities;
  36. using Nini.Config;
  37. using OpenMetaverse;
  38. using System;
  39. using System.Collections.Generic;
  40. using System.Threading;
  41. namespace Aurora.BotManager
  42. {
  43. public class BotManager : INonSharedRegionModule, IBotManager
  44. {
  45. private readonly Dictionary<UUID, Bot> m_bots = new Dictionary<UUID, Bot>();
  46. #region INonSharedRegionModule Members
  47. public void Initialise(IConfigSource source)
  48. {
  49. }
  50. public void AddRegion(IScene scene)
  51. {
  52. scene.RegisterModuleInterface<IBotManager>(this);
  53. scene.RegisterModuleInterface(this);
  54. }
  55. public void RemoveRegion(IScene scene)
  56. {
  57. }
  58. public void RegionLoaded(IScene scene)
  59. {
  60. }
  61. public void Close()
  62. {
  63. m_bots.Clear();
  64. }
  65. public Type ReplaceableInterface
  66. {
  67. get { return null; }
  68. }
  69. public string Name
  70. {
  71. get { return GetType().AssemblyQualifiedName; }
  72. }
  73. #endregion
  74. #region IBotManager
  75. /// <summary>
  76. /// Creates a new bot inworld
  77. /// </summary>
  78. /// <param name="firstName"></param>
  79. /// <param name="lastName"></param>
  80. /// <param name="scene"></param>
  81. /// <param name="cloneAppearanceFrom">UUID of the avatar whos appearance will be copied to give this bot an appearance</param>
  82. /// <param name="creatorID"></param>
  83. /// <param name="startPos"></param>
  84. /// <returns>ID of the bot</returns>
  85. public UUID CreateAvatar(string firstName, string lastName, IScene scene, UUID cloneAppearanceFrom,
  86. UUID creatorID, Vector3 startPos)
  87. {
  88. AgentCircuitData m_aCircuitData = new AgentCircuitData
  89. {
  90. child = false,
  91. circuitcode = (uint) Util.RandomClass.Next(),
  92. Appearance = GetAppearance(cloneAppearanceFrom, scene)
  93. };
  94. //Add the circuit data so they can login
  95. //Sets up appearance
  96. if (m_aCircuitData.Appearance == null)
  97. {
  98. m_aCircuitData.Appearance = new AvatarAppearance {Wearables = AvatarWearable.DefaultWearables};
  99. }
  100. //Create the new bot data
  101. BotClientAPI m_character = new BotClientAPI(scene, m_aCircuitData)
  102. {
  103. FirstName = firstName,
  104. LastName = lastName
  105. };
  106. m_aCircuitData.AgentID = m_character.AgentId;
  107. m_aCircuitData.Appearance.Owner = m_character.AgentId;
  108. List<AvatarAttachment> attachments = m_aCircuitData.Appearance.GetAttachments();
  109. m_aCircuitData.Appearance.ClearAttachments();
  110. foreach (AvatarAttachment t in attachments)
  111. {
  112. InventoryItemBase item = scene.InventoryService.GetItem(UUID.Zero, t.ItemID);
  113. if (item != null)
  114. {
  115. item.ID = UUID.Random();
  116. item.Owner = m_character.AgentId;
  117. item.Folder = UUID.Zero;
  118. scene.InventoryService.AddItemAsync(item, null);
  119. //Now fix the ItemID
  120. m_aCircuitData.Appearance.SetAttachment(t.AttachPoint, item.ID, t.AssetID);
  121. }
  122. }
  123. scene.AuthenticateHandler.AgentCircuits.Add(m_character.CircuitCode, m_aCircuitData);
  124. //This adds them to the scene and sets them inworld
  125. AddAndWaitUntilAgentIsAdded(scene, m_character);
  126. IScenePresence SP = scene.GetScenePresence(m_character.AgentId);
  127. if (SP == null)
  128. return UUID.Zero; //Failed!
  129. Bot bot = new Bot();
  130. bot.Initialize(SP, creatorID);
  131. SP.MakeRootAgent(startPos, false, true);
  132. //Move them
  133. SP.Teleport(startPos);
  134. foreach (var presence in scene.GetScenePresences())
  135. presence.SceneViewer.QueuePresenceForUpdate(SP, PrimUpdateFlags.ForcedFullUpdate);
  136. IAttachmentsModule attModule = SP.Scene.RequestModuleInterface<IAttachmentsModule>();
  137. if (attModule != null)
  138. foreach (AvatarAttachment att in attachments)
  139. attModule.RezSingleAttachmentFromInventory(SP.ControllingClient, att.ItemID, att.AssetID, 0, true);
  140. IAvatarAppearanceModule appearance = SP.RequestModuleInterface<IAvatarAppearanceModule>();
  141. appearance.InitialHasWearablesBeenSent = true;
  142. //Save them in the bots list
  143. m_bots.Add(m_character.AgentId, bot);
  144. AddTagToBot(m_character.AgentId, "AllBots", bot.AvatarCreatorID);
  145. MainConsole.Instance.Info("[RexBotManager]: Added bot " + m_character.Name + " to scene.");
  146. //Return their UUID
  147. return m_character.AgentId;
  148. }
  149. private static void AddAndWaitUntilAgentIsAdded(IScene scene, BotClientAPI m_character)
  150. {
  151. bool done = false;
  152. scene.AddNewClient(m_character, delegate { done = true; });
  153. while (!done)
  154. Thread.Sleep(3);
  155. }
  156. public void RemoveAvatar(UUID avatarID, IScene scene, UUID userAttempting)
  157. {
  158. IEntity sp = scene.GetScenePresence(avatarID);
  159. if (sp == null)
  160. {
  161. sp = scene.GetSceneObjectPart(avatarID);
  162. if (sp == null)
  163. return;
  164. sp = ((ISceneChildEntity) sp).ParentEntity;
  165. }
  166. if (!CheckPermission(sp, userAttempting))
  167. return;
  168. RemoveAllTagsFromBot(avatarID, userAttempting);
  169. if (!m_bots.Remove(avatarID))
  170. return;
  171. //Kill the agent
  172. IEntityTransferModule module = scene.RequestModuleInterface<IEntityTransferModule>();
  173. module.IncomingCloseAgent(scene, avatarID);
  174. }
  175. public void PauseMovement(UUID botID, UUID userAttempting)
  176. {
  177. Bot bot;
  178. //Find the bot
  179. if (m_bots.TryGetValue(botID, out bot))
  180. {
  181. if (!CheckPermission(bot, userAttempting))
  182. return;
  183. bot.PauseMovement();
  184. }
  185. }
  186. public void ResumeMovement(UUID botID, UUID userAttempting)
  187. {
  188. Bot bot;
  189. //Find the bot
  190. if (m_bots.TryGetValue(botID, out bot))
  191. {
  192. if (!CheckPermission(bot, userAttempting))
  193. return;
  194. bot.ResumeMovement();
  195. }
  196. }
  197. /// <summary>
  198. /// Sets up where the bot should be walking
  199. /// </summary>
  200. /// <param name="botID">ID of the bot</param>
  201. /// <param name="positions">List of positions the bot will move to</param>
  202. /// <param name="mode">List of what the bot should be doing inbetween the positions</param>
  203. /// <param name="flags"></param>
  204. /// <param name="userAttempting"></param>
  205. public void SetBotMap(UUID botID, List<Vector3> positions, List<TravelMode> mode, int flags, UUID userAttempting)
  206. {
  207. Bot bot;
  208. //Find the bot
  209. if (m_bots.TryGetValue(botID, out bot))
  210. {
  211. if (!CheckPermission(bot, userAttempting))
  212. return;
  213. bot.SetPath(positions, mode, flags);
  214. }
  215. }
  216. /// <summary>
  217. /// Speed up or slow down the bot
  218. /// </summary>
  219. /// <param name="botID"></param>
  220. /// <param name="modifier"></param>
  221. /// <param name="userAttempting"></param>
  222. public void SetMovementSpeedMod(UUID botID, float modifier, UUID userAttempting)
  223. {
  224. Bot bot;
  225. if (m_bots.TryGetValue(botID, out bot))
  226. {
  227. if (!CheckPermission(bot, userAttempting))
  228. return;
  229. bot.SetMovementSpeedMod(modifier);
  230. }
  231. }
  232. public void SetBotShouldFly(UUID botID, bool shouldFly, UUID userAttempting)
  233. {
  234. Bot bot;
  235. if (m_bots.TryGetValue(botID, out bot))
  236. {
  237. if (!CheckPermission(bot, userAttempting))
  238. return;
  239. if (shouldFly)
  240. bot.DisableWalk();
  241. else
  242. bot.EnableWalk();
  243. }
  244. }
  245. #region Tag/Remove bots
  246. private readonly Dictionary<string, List<UUID>> m_botTags = new Dictionary<string, List<UUID>>();
  247. public void AddTagToBot(UUID Bot, string tag, UUID userAttempting)
  248. {
  249. Bot bot;
  250. if (m_bots.TryGetValue(Bot, out bot))
  251. {
  252. if (!CheckPermission(bot, userAttempting))
  253. return;
  254. }
  255. if (!m_botTags.ContainsKey(tag))
  256. m_botTags.Add(tag, new List<UUID>());
  257. m_botTags[tag].Add(Bot);
  258. }
  259. public List<UUID> GetBotsWithTag(string tag)
  260. {
  261. if (!m_botTags.ContainsKey(tag))
  262. return new List<UUID>();
  263. return new List<UUID>(m_botTags[tag]);
  264. }
  265. public void RemoveBots(string tag, UUID userAttempting)
  266. {
  267. List<UUID> bots = GetBotsWithTag(tag);
  268. foreach (UUID bot in bots)
  269. {
  270. Bot Bot;
  271. if (m_bots.TryGetValue(bot, out Bot))
  272. {
  273. if (!CheckPermission(Bot, userAttempting))
  274. continue;
  275. RemoveTagFromBot(bot, tag, userAttempting);
  276. RemoveAvatar(bot, Bot.Controller.GetScene(), userAttempting);
  277. }
  278. }
  279. }
  280. public void RemoveTagFromBot(UUID Bot, string tag, UUID userAttempting)
  281. {
  282. Bot bot;
  283. if (m_bots.TryGetValue(Bot, out bot))
  284. {
  285. if (!CheckPermission(bot, userAttempting))
  286. return;
  287. }
  288. if (m_botTags.ContainsKey(tag))
  289. m_botTags[tag].Remove(Bot);
  290. }
  291. public void RemoveAllTagsFromBot(UUID Bot, UUID userAttempting)
  292. {
  293. Bot bot;
  294. if (m_bots.TryGetValue(Bot, out bot))
  295. {
  296. if (!CheckPermission(bot, userAttempting))
  297. return;
  298. }
  299. List<string> tagsToRemove = new List<string>();
  300. foreach (KeyValuePair<string, List<UUID>> kvp in m_botTags)
  301. {
  302. if (kvp.Value.Contains(Bot))
  303. tagsToRemove.Add(kvp.Key);
  304. }
  305. foreach (string tag in tagsToRemove)
  306. m_botTags[tag].Remove(Bot);
  307. }
  308. #endregion
  309. /// <summary>
  310. /// Finds the given users appearance
  311. /// </summary>
  312. /// <param name="target"></param>
  313. /// <param name="scene"></param>
  314. /// <returns></returns>
  315. private AvatarAppearance GetAppearance(UUID target, IScene scene)
  316. {
  317. IScenePresence sp = scene.GetScenePresence(target);
  318. if (sp != null)
  319. {
  320. IAvatarAppearanceModule aa = sp.RequestModuleInterface<IAvatarAppearanceModule>();
  321. if (aa != null)
  322. return new AvatarAppearance(aa.Appearance);
  323. }
  324. return scene.AvatarService.GetAppearance(target);
  325. }
  326. private bool CheckPermission(IEntity sp, UUID userAttempting)
  327. {
  328. foreach (Bot bot in m_bots.Values)
  329. {
  330. if (bot.Controller.UUID == sp.UUID)
  331. return bot.AvatarCreatorID == userAttempting;
  332. }
  333. return false;
  334. }
  335. private bool CheckPermission(Bot bot, UUID userAttempting)
  336. {
  337. if (userAttempting == UUID.Zero)
  338. return true; //Forced override
  339. if (bot != null)
  340. return bot.AvatarCreatorID == userAttempting;
  341. return false;
  342. }
  343. #endregion
  344. #region IBotManager
  345. /// <summary>
  346. /// Begins to follow the given user
  347. /// </summary>
  348. /// <param name="botID"></param>
  349. /// <param name="avatarName"></param>
  350. /// <param name="startFollowDistance"></param>
  351. /// <param name="endFollowDistance"></param>
  352. /// <param name="requireLOS"></param>
  353. /// <param name="offsetFromAvatar"></param>
  354. /// <param name="userAttempting"></param>
  355. public void FollowAvatar(UUID botID, string avatarName, float startFollowDistance, float endFollowDistance,
  356. bool requireLOS, Vector3 offsetFromAvatar, UUID userAttempting)
  357. {
  358. Bot bot;
  359. if (m_bots.TryGetValue(botID, out bot))
  360. {
  361. if (!CheckPermission(bot, userAttempting))
  362. return;
  363. bot.FollowAvatar(avatarName, startFollowDistance, endFollowDistance, offsetFromAvatar, requireLOS);
  364. }
  365. }
  366. /// <summary>
  367. /// Stops following the given user
  368. /// </summary>
  369. /// <param name="botID"></param>
  370. /// <param name="userAttempting"></param>
  371. public void StopFollowAvatar(UUID botID, UUID userAttempting)
  372. {
  373. Bot bot;
  374. if (m_bots.TryGetValue(botID, out bot))
  375. {
  376. if (!CheckPermission(bot, userAttempting))
  377. return;
  378. bot.StopFollowAvatar();
  379. }
  380. }
  381. /// <summary>
  382. /// Sends a chat message to all clients
  383. /// </summary>
  384. /// <param name="botID"></param>
  385. /// <param name="message"></param>
  386. /// <param name="sayType"></param>
  387. /// <param name="channel"></param>
  388. /// <param name="userAttempting"></param>
  389. public void SendChatMessage(UUID botID, string message, int sayType, int channel, UUID userAttempting)
  390. {
  391. Bot bot;
  392. if (m_bots.TryGetValue(botID, out bot))
  393. {
  394. if (!CheckPermission(bot, userAttempting))
  395. return;
  396. bot.SendChatMessage(sayType, message, channel);
  397. }
  398. }
  399. /// <summary>
  400. /// Sends a chat message to all clients
  401. /// </summary>
  402. /// <param name="botID"></param>
  403. /// <param name="toUser"></param>
  404. /// <param name="message"></param>
  405. /// <param name="userAttempting"></param>
  406. public void SendIM(UUID botID, UUID toUser, string message, UUID userAttempting)
  407. {
  408. Bot bot;
  409. if (m_bots.TryGetValue(botID, out bot))
  410. {
  411. if (!CheckPermission(bot, userAttempting))
  412. return;
  413. bot.SendInstantMessage(new GridInstantMessage
  414. {
  415. binaryBucket = new byte[0],
  416. dialog = (byte) InstantMessageDialog.MessageFromAgent,
  417. message = message,
  418. fromAgentID = botID,
  419. fromAgentName = bot.Controller.Name,
  420. fromGroup = false,
  421. imSessionID = UUID.Random(),
  422. offline = 0,
  423. ParentEstateID = 0,
  424. RegionID = bot.Controller.GetScene().RegionInfo.RegionID,
  425. timestamp = (uint) Util.UnixTimeSinceEpoch(),
  426. toAgentID = toUser
  427. });
  428. }
  429. }
  430. #endregion
  431. #region Character Management
  432. public void CreateCharacter(UUID primID, IScene scene)
  433. {
  434. RemoveCharacter(primID);
  435. ISceneEntity entity = scene.GetSceneObjectPart(primID).ParentEntity;
  436. Bot bot = new Bot();
  437. bot.Initialize(entity);
  438. m_bots.Add(primID, bot);
  439. AddTagToBot(primID, "AllBots", bot.AvatarCreatorID);
  440. }
  441. public IBotController GetCharacterManager(UUID primID)
  442. {
  443. foreach (Bot bot in m_bots.Values)
  444. {
  445. if (bot.Controller.UUID == primID)
  446. return bot.Controller;
  447. }
  448. return null;
  449. }
  450. public void RemoveCharacter(UUID primID)
  451. {
  452. if (m_bots.ContainsKey(primID))
  453. {
  454. Bot b = m_bots[primID];
  455. b.Close(true);
  456. RemoveAllTagsFromBot(primID, UUID.Zero);
  457. m_bots.Remove(primID);
  458. }
  459. }
  460. #endregion
  461. }
  462. }