PageRenderTime 29ms CodeModel.GetById 14ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

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