/// <summary> /// Sends an avatars appearance (only called by the TimeSender) /// </summary> /// <param name="agentid"></param> /// <param name="app"></param> private void HandleAppearanceSend(UUID agentid, AvatarAppearance app) { IScenePresence sp = m_scene.GetScenePresence(agentid); if (sp == null) { MainConsole.Instance.WarnFormat( "[AvatarFactory]: Agent {0} no longer in the scene to send appearance for.", agentid); return; } IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule>(); // MainConsole.Instance.WarnFormat("[AvatarFactory]: Handle appearance send for {0}", agentid); // Send the appearance to everyone in the scene appearance.SendAppearanceToAllOtherAgents(); // Send animations back to the avatar as well sp.Animator.SendAnimPack(); }
public void ResumeAvatar(IScenePresence presence) { Util.FireAndForget(delegate { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); if (null == appearance || null == appearance.Appearance) { MainConsole.Instance.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", presence.UUID); return; } //Create the avatar attachments plugin for the av AvatarAttachments attachmentsPlugin = new AvatarAttachments(presence); presence.RegisterModuleInterface(attachmentsPlugin); List <AvatarAttachment> attachments = appearance.Appearance.GetAttachments(); foreach (AvatarAttachment attach in attachments) { try { RezSingleAttachmentFromInventory(presence.ControllingClient, attach.ItemID, attach.AssetID, 0, false); } catch (Exception e) { MainConsole.Instance.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e); } } presence.AttachmentsLoaded = true; lock (_usersToSendAttachmentsToWhenLoaded) { if (_usersToSendAttachmentsToWhenLoaded.ContainsKey(presence.UUID)) { foreach (var id in _usersToSendAttachmentsToWhenLoaded[presence.UUID]) { SendAttachmentsToPresence(id, presence); } _usersToSendAttachmentsToWhenLoaded.Remove(presence.UUID); } } }); }
protected void SendFullUpdateForPresence(IScenePresence presence) { Util.FireAndForget(delegate { m_presence.ControllingClient.SendAvatarDataImmediate(presence); //Send the animations too presence.Animator.SendAnimPackToClient(m_presence.ControllingClient); //Send the presence of this agent to us IAvatarAppearanceModule module = presence.RequestModuleInterface <IAvatarAppearanceModule>(); if (module != null) { module.SendAppearanceToAgent(m_presence); } //We need to send all attachments of this avatar as well IAttachmentsModule attmodule = m_presence.Scene.RequestModuleInterface <IAttachmentsModule>(); if (attmodule != null) { ISceneEntity[] entities = attmodule.GetAttachmentsForAvatar(m_presence.UUID); foreach (ISceneEntity entity in entities) { QueuePartForUpdate(entity.RootChild, PrimUpdateFlags.ForcedFullUpdate); #if (!ISWIN) foreach (ISceneChildEntity child in entity.ChildrenEntities()) { if (!child.IsRoot) { QueuePartForUpdate(child, PrimUpdateFlags.ForcedFullUpdate); } } #else foreach (ISceneChildEntity child in entity.ChildrenEntities().Where(child => !child.IsRoot)) { QueuePartForUpdate(child, PrimUpdateFlags.ForcedFullUpdate); } #endif } } }); }
public void ForceSendAvatarAppearance(UUID agentid) { //If the avatar changes appearance, then proptly logs out, this will break! IScenePresence sp = m_scene.GetScenePresence(agentid); if (sp == null || sp.IsChildAgent) { m_log.WarnFormat("[AvatarFactory]: Agent {0} no longer in the scene", agentid); return; } //Force send! IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); sp.ControllingClient.SendWearables(appearance.Appearance.Wearables, appearance.Appearance.Serial); appearance.SendAvatarDataToAllAgents(); appearance.SendAppearanceToAgent(sp); appearance.SendAppearanceToAllOtherAgents(); }
public void QueueInitialAppearanceSend(UUID agentid) { if (MainConsole.Instance.Threshold <= Level.Debug) { MainConsole.Instance.DebugFormat("[AvatarFactory]: Queue initial appearance send for {0}", GetAgentName(agentid)); } IScenePresence sp = m_scene.GetScenePresence(agentid); if (sp == null) { MainConsole.Instance.WarnFormat("[AvatarFactory]: Agent {0} no longer in the scene", GetAgentName(agentid)); return; } IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); //We're waiting to send them, so mark it as true appearance.InitialHasWearablesBeenSent = true; _initialSendQueue.Add(agentid); }
/// <summary> /// Update what the avatar is wearing using an item from their inventory. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e) { IScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp == null) { m_log.WarnFormat("[AvatarFactory]: AvatarIsWearing unable to find presence for {0}", client.AgentId); return; } m_log.DebugFormat("[AvatarFactory]: AvatarIsWearing called for {0}", client.AgentId); // operate on a copy of the appearance so we don't have to lock anything IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); AvatarAppearance avatAppearance = new AvatarAppearance(appearance.Appearance, false); foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) { if (wear.Type < AvatarWearable.MAX_WEARABLES) { avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); } } avatAppearance.GetAssetsFrom(appearance.Appearance); // This could take awhile since it needs to pull inventory SetAppearanceAssets(sp.UUID, ref avatAppearance); // could get fancier with the locks here, but in the spirit of "last write wins" // this should work correctly, also, we don't need to send the appearance here // since the "iswearing" will trigger a new set of visual param and baked texture changes // when those complete, the new appearance will be sent appearance.Appearance = avatAppearance; //Send the wearables HERE so that the client knows what it is wearing //sp.ControllingClient.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial); //Do not save or send the appearance! The client loops back and sends a bunch of SetAppearance // (handled above) and that takes care of it }
/// <summary> /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in /// </summary> /// <param name="remoteClient"></param> /// <param name="regionHandle"></param> /// <param name="position"></param> /// <param name="lookAt"></param> /// <param name="flags"></param> public void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) { Scene scene = (Scene)remoteClient.Scene; if (scene == null) { return; } IScenePresence SP = scene.GetScenePresence(remoteClient.AgentId); IDialogModule module = scene.RequestModuleInterface <IDialogModule>(); if (SP != null) { if (scene.Permissions.CanSetHome(SP.UUID)) { IAvatarAppearanceModule appearance = SP.RequestModuleInterface <IAvatarAppearanceModule> (); position.Z += appearance.Appearance.AvatarHeight / 2; IAgentInfoService agentInfoService = scene.RequestModuleInterface <IAgentInfoService>(); if (agentInfoService != null && agentInfoService.SetHomePosition(remoteClient.AgentId.ToString(), scene.RegionInfo.RegionID, position, lookAt) && module != null) //Do this last so it doesn't screw up the rest { // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. module.SendAlertToUser(remoteClient, "Home position set."); } else if (module != null) { module.SendAlertToUser(remoteClient, "Set Home request failed."); } } else if (module != null) { module.SendAlertToUser(remoteClient, "Set Home request failed: Permissions do not allow the setting of home here."); } } }
public void QueueAppearanceSave(UUID agentid) { // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); // 10000 ticks per millisecond, 1000 milliseconds per second long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); lock (m_savequeue) { IScenePresence sp = m_scene.GetScenePresence(agentid); if (sp == null) { m_log.WarnFormat("[AvatarFactory]: Agent {0} no longer in the scene", agentid); return; } IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); m_savequeue[agentid] = timestamp; lock (m_saveQueueData) { m_saveQueueData[agentid] = appearance.Appearance; } m_updateTimer.Start(); } }
public UUID CreateAvatar(string firstName, string lastName, IScene scene, AvatarAppearance avatarApp, UUID creatorID, Vector3 startPos) { //Add the circuit data so they can login AgentCircuitData m_aCircuitData = new AgentCircuitData { IsChildAgent = false, CircuitCode = (uint)Util.RandomClass.Next() }; //Create the new bot data BotClientAPI m_character = new BotClientAPI(scene, m_aCircuitData); m_character.Name = firstName + " " + lastName; m_aCircuitData.AgentID = m_character.AgentId; //Set up appearance var origOwner = avatarApp.Owner; avatarApp.Owner = m_character.AgentId; List <AvatarAttachment> attachments = avatarApp.GetAttachments(); avatarApp.ClearAttachments(); // get original attachments foreach (AvatarAttachment t in attachments) { InventoryItemBase item = scene.InventoryService.GetItem(origOwner, t.ItemID); if (item != null) { item.ID = UUID.Random(); item.Owner = m_character.AgentId; item.Folder = UUID.Zero; scene.InventoryService.AddCacheItemAsync(item); //Now fix the ItemID avatarApp.SetAttachment(t.AttachPoint, item.ID, t.AssetID); } } scene.AuthenticateHandler.AgentCircuits.Add(m_character.CircuitCode, m_aCircuitData); //This adds them to the scene and sets them in world AddAndWaitUntilAgentIsAdded(scene, m_character); IScenePresence SP = scene.GetScenePresence(m_character.AgentId); if (SP == null) { return(UUID.Zero); //Failed! } // set this as a NPC character SP.IsNpcAgent = true; IAvatarAppearanceModule appearance = SP.RequestModuleInterface <IAvatarAppearanceModule>(); appearance.Appearance = avatarApp; appearance.InitialHasWearablesBeenSent = true; Bot bot = new Bot(); bot.Initialize(SP, creatorID); try { SP.MakeRootAgent(startPos, false, true); } catch { MainConsole.Instance.ErrorFormat("[BotManager]: Error creating bot {0} as root agent!", m_character.AgentId); } //Move them SP.Teleport(startPos); foreach (var presence in scene.GetScenePresences()) { presence.SceneViewer.QueuePresenceForUpdate(SP, PrimUpdateFlags.ForcedFullUpdate); } IAttachmentsModule attModule = SP.Scene.RequestModuleInterface <IAttachmentsModule>(); if (attModule != null) { foreach (AvatarAttachment att in attachments) { attModule.RezSingleAttachmentFromInventory(SP.ControllingClient, att.ItemID, att.AssetID, 0, true); } } //Save them in the bots list m_bots.Add(m_character.AgentId, bot); AddTagToBot(m_character.AgentId, "AllBots", bot.AvatarCreatorID); MainConsole.Instance.InfoFormat("[BotManager]: Added bot {0} to region {1}", m_character.Name, scene.RegionInfo.RegionName); //Return their UUID return(m_character.AgentId); }
/// <summary> /// Set appearance data (textureentry and slider settings) received from the client /// </summary> /// <param name="texture"></param> /// <param name="visualParam"></param> public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCache[] wearables) { IScenePresence sp = m_scene.GetScenePresence(client.AgentId); IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); if (sp == null) { m_log.WarnFormat("[AvatarFactory]: SetAppearance unable to find presence for {0}", client.AgentId); return; } //m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId); // Process the texture entry transactionally, this doesn't guarantee that Appearance is // going to be handled correctly but it does serialize the updates to the appearance lock (m_setAppearanceLock) { bool texturesChanged = false; bool visualParamsChanged = false; if (textureEntry != null) { List <UUID> ChangedTextures = new List <UUID>(); texturesChanged = appearance.Appearance.SetTextureEntries(textureEntry, out ChangedTextures); // m_log.WarnFormat("[AVFACTORY]: Prepare to check textures for {0}",client.AgentId); //Do this async as it accesses the asset service (could be remote) multiple times Util.FireAndForget(delegate(object o) { //Validate all the textures now that we've updated ValidateBakedTextureCache(client, false); //The client wants us to cache the baked textures CacheWearableData(sp, textureEntry, wearables); }); // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); } // Process the visual params, this may change height as well if (visualParams != null) { //Now update the visual params and see if they have changed visualParamsChanged = appearance.Appearance.SetVisualParams(visualParams); //Fix the height only if the parameters have changed if (visualParamsChanged && appearance.Appearance.AvatarHeight > 0) { sp.SetHeight(appearance.Appearance.AvatarHeight); } } // Process the baked texture array if (textureEntry != null) { //Check for banned clients here Aurora.Framework.IBanViewersModule module = client.Scene.RequestModuleInterface <Aurora.Framework.IBanViewersModule>(); if (module != null) { module.CheckForBannedViewer(client, textureEntry); } } // If something changed in the appearance then queue an appearance save if (texturesChanged || visualParamsChanged) { QueueAppearanceSave(client.AgentId); } } // And always queue up an appearance update to send out QueueAppearanceSend(client.AgentId); // m_log.WarnFormat("[AVFACTORY]: complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); }
public virtual void DoTeleport(IScenePresence sp, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags) { sp.ControllingClient.SendTeleportProgress(teleportFlags, "sending_dest"); if (finalDestination == null) { sp.ControllingClient.SendTeleportFailed("Unable to locate destination"); return; } m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}/{2}", finalDestination.ServerURI, finalDestination.RegionName, position); sp.ControllingClient.SendTeleportProgress(teleportFlags, "arriving"); // Fixing a bug where teleporting while sitting results in the avatar ending up removed from // both regions if (sp.ParentID != UUID.Zero) { sp.StandUp(); } //Make sure that all attachments are ready for the teleport IAttachmentsModule attModule = sp.Scene.RequestModuleInterface <IAttachmentsModule>(); if (attModule != null) { attModule.ValidateAttachments(sp.UUID); } AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); agentCircuit.startpos = position; //The agent will be a root agent agentCircuit.child = false; //Make sure the appearnace is right IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); agentCircuit.Appearance = appearance.Appearance; AgentData agent = new AgentData(); sp.CopyTo(agent); //Fix the position agent.Position = position; IEventQueueService eq = sp.Scene.RequestModuleInterface <IEventQueueService>(); if (eq != null) { ISyncMessagePosterService syncPoster = sp.Scene.RequestModuleInterface <ISyncMessagePosterService>(); if (syncPoster != null) { //This does CreateAgent and sends the EnableSimulator/EstablishAgentCommunication/TeleportFinish // messages if they need to be called and deals with the callback OSDMap map = syncPoster.Get(SyncMessageHelper.TeleportAgent((int)sp.DrawDistance, agentCircuit, agent, teleportFlags, finalDestination, sp.Scene.RegionInfo.RegionHandle), sp.Scene.RegionInfo.RegionHandle); bool result = map["Success"].AsBoolean(); if (!result) { // Fix the agent status sp.IsChildAgent = false; sp.ControllingClient.SendTeleportFailed(map["Reason"].AsString()); return; } } } //Kill the groups here, otherwise they will become ghost attachments // and stay in the sim, they'll get readded below into the new sim KillAttachments(sp); // Well, this is it. The agent is over there. KillEntity(sp.Scene, sp); //Make it a child agent for now... the grid will kill us later if we need to close sp.MakeChildAgent(); }
/// <summary> /// Adding a New Client and Create a Presence for it. /// Called by the LLClientView when the UseCircuitCode packet comes in /// Used by NPCs to add themselves to the Scene /// </summary> /// <param name="client"></param> /// <param name="completed"></param> public void AddNewClient(IClientAPI client, BlankHandler completed) { lock (m_events) m_events.Add(delegate { try { System.Net.IPEndPoint ep = (System.Net.IPEndPoint)client.GetClientEP(); AgentCircuitData aCircuit = AuthenticateHandler.AuthenticateSession(client.SessionId, client.AgentId, client.CircuitCode, ep); if (aCircuit == null) // no good, didn't pass NewUserConnection successfully { completed(); return; } m_clientManager.Add(client); //Create the scenepresence IScenePresence sp = CreateAndAddChildScenePresence(client); sp.IsChildAgent = aCircuit.child; sp.DrawDistance = aCircuit.DrawDistance; //Trigger events m_eventManager.TriggerOnNewPresence(sp); //Make sure the appearanace is updated IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule>(); if (appearance != null) { appearance.Appearance = aCircuit.Appearance ?? sp.Scene.AvatarService.GetAppearance(sp.UUID); if (appearance.Appearance == null) { MainConsole.Instance.Error("[AsyncScene]: NO AVATAR APPEARANCE FOUND FOR " + sp.Name); appearance.Appearance = new AvatarAppearance(sp.UUID); } } if (GetScenePresence(client.AgentId) != null) { EventManager.TriggerOnNewClient(client); if ((aCircuit.teleportFlags & (uint)TeleportFlags.ViaLogin) != 0) { EventManager.TriggerOnClientLogin(client); } } //Add the client to login stats ILoginMonitor monitor3 = (ILoginMonitor)RequestModuleInterface <IMonitorModule>().GetMonitor("", MonitorModuleHelper.LoginMonitor); if ((aCircuit.teleportFlags & (uint)TeleportFlags.ViaLogin) != 0 && monitor3 != null) { monitor3.AddSuccessfulLogin(); } if (sp.IsChildAgent)//If we're a child, trigger this so that we get updated in the modules { sp.TriggerSignificantClientMovement(); } completed(); } catch (Exception ex) { MainConsole.Instance.Warn("[Scene]: Error in AddNewClient: " + ex); } }); }
public ISceneEntity RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, int AttachmentPt) { MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { SceneObjectGroup objatt = invAccess.CreateObjectFromInventory(remoteClient, itemID); if (objatt != null) { #region Set up object for attachment status InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); if (item == null) { return(null); } objatt.RootPart.Flags |= PrimFlags.Phantom; objatt.RootPart.IsAttachment = true; objatt.SetFromItemID(itemID, item.AssetID); // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. objatt.RootPart.Name = item.Name; objatt.RootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart>(objatt.ChildrenList); foreach (SceneObjectPart part in partList) { part.AttachedAvatar = remoteClient.AgentId; } objatt.SetGroup(remoteClient.ActiveGroupId, remoteClient.AgentId); if (objatt.RootPart.OwnerID != item.Owner) { //Need to kill the for sale here objatt.RootPart.ObjectSaleType = 0; objatt.RootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } objatt.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } } objatt.RootPart.TrimPermissions(); objatt.RootPart.IsAttachment = true; objatt.IsDeleted = false; //Update the ItemID with the new item objatt.SetFromItemID(itemID, item.AssetID); //DO NOT SEND THIS KILL ENTITY // If we send this, when someone copies an inworld object, then wears it, the inworld objects disapepars // If a bug is caused by this, we need to figure out some other workaround. //SendKillEntity(objatt.RootChild); //We also have to reset the IDs so that it doesn't have the same IDs as one inworld (possibly)! m_scene.SceneGraph.PrepPrimForAdditionToScene(objatt); m_scene.Entities.Add(objatt); //If we updated the attachment, we need to save the change IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence != null) { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); AvatarAttachments attPlugin = presence.RequestModuleInterface <AvatarAttachments>(); bool save = appearance.Appearance.CheckWhetherAttachmentChanged(AttachmentPt, item.ID, item.AssetID); attPlugin.AddAttachment(objatt); appearance.Appearance.SetAttachments(attPlugin.Get()); if (save) { AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); } MainConsole.Instance.InfoFormat( "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2} localID {3}", objatt.Name, remoteClient.Name, AttachmentPt, objatt.LocalId); FindAttachmentPoint(remoteClient, objatt.LocalId, objatt, AttachmentPt, item); } else { objatt = null;//Presence left, kill the attachment } #endregion } else { MainConsole.Instance.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, remoteClient.Name, AttachmentPt); } return(objatt); } return(null); }
protected void HandleSaveAvatarArchive(string[] cmdparams) { if (cmdparams.Length < 7) { MainConsole.Instance.Info("[AvatarArchive] Not enough parameters!"); } UserAccount account = UserAccountService.GetUserAccount(null, cmdparams[3] + " " + cmdparams[4]); if (account == null) { MainConsole.Instance.Error("[AvatarArchive] User not found!"); return; } IScenePresence SP = null; ISceneManager manager = m_registry.RequestModuleInterface <ISceneManager>(); if (manager != null) { foreach (IScene scene in manager.GetAllScenes()) { if (scene.TryGetScenePresence(account.PrincipalID, out SP)) { break; } } if (SP == null) { return; //Bad people! } } if (SP != null) { SP.ControllingClient.SendAlertMessage("Appearance saving in progress..."); } AvatarAppearance appearance = AvatarService.GetAppearance(account.PrincipalID); if (appearance == null) { IAvatarAppearanceModule appearancemod = m_registry.RequestModuleInterface <IAvatarAppearanceModule>(); appearance = appearancemod.Appearance; } OSDMap map = new OSDMap(); OSDMap body = new OSDMap(); OSDMap assets = new OSDMap(); OSDMap items = new OSDMap(); body = appearance.Pack(); body.Add("FolderName", OSD.FromString(cmdparams[6])); foreach (AvatarWearable wear in appearance.Wearables) { for (int i = 0; i < wear.Count; i++) { WearableItem w = wear[i]; if (w.AssetID != UUID.Zero) { SaveItem(w.ItemID, items, assets); SaveAsset(w.AssetID, assets); } } } List <AvatarAttachment> attachments = appearance.GetAttachments(); #if (!ISWIN) foreach (AvatarAttachment a in attachments) { if (a.AssetID != UUID.Zero) { SaveItem(a.ItemID, items, assets); SaveAsset(a.AssetID, assets); } } #else foreach (AvatarAttachment a in attachments.Where(a => a.AssetID != UUID.Zero)) { SaveItem(a.ItemID, items, assets); SaveAsset(a.AssetID, assets); } #endif map.Add("Body", body); map.Add("Assets", assets); map.Add("Items", items); //Write the map if (cmdparams[5].EndsWith(".database")) { IAvatarArchiverConnector archiver = DataManager.DataManager.RequestPlugin <IAvatarArchiverConnector>(); if (archiver != null) { AvatarArchive archive = new AvatarArchive(); archive.ArchiveXML = OSDParser.SerializeLLSDXmlString(map); // Add the extra details for archives archive.Name = cmdparams[5].Substring(0, cmdparams[5].LastIndexOf(".database")); if (cmdparams.Length > 7) { if (cmdparams.Contains("--snapshot")) { UUID snapshot; int index = 0; for (; index < cmdparams.Length; index++) { if (cmdparams[index] == "--snapshot") { index++; break; } } if (index < cmdparams.Length && UUID.TryParse(cmdparams[index], out snapshot)) { archive.Snapshot = snapshot.ToString(); } } else { archive.Snapshot = UUID.Zero.ToString(); } if (cmdparams.Contains("--public")) { archive.IsPublic = 1; } } else { archive.Snapshot = UUID.Zero.ToString(); archive.IsPublic = 0; } // Save the archive archiver.SaveAvatarArchive(archive); MainConsole.Instance.Info("[AvatarArchive] Saved archive to database as: " + archive.Name); } else { MainConsole.Instance.Error("[AvatarArchive] Unable to save to database!"); return; } } else { StreamWriter writer = new StreamWriter(cmdparams[5], false); writer.Write(OSDParser.SerializeLLSDXmlString(map)); writer.Close(); writer.Dispose(); MainConsole.Instance.Info("[AvatarArchive] Saved archive to " + cmdparams[5]); } }
/// <summary> /// This Closes child agents on neighboring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// </summary> protected IScenePresence CrossAgentToNewRegionAsync(IScenePresence agent, Vector3 pos, GridRegion crossingRegion, bool isFlying) { m_log.DebugFormat("[EntityTransferModule]: Crossing agent {0} to region {1}", agent.Name, crossingRegion.RegionName); IScene m_scene = agent.Scene; if (crossingRegion != null) { //Make sure that all attachments are ready for the teleport IAttachmentsModule attModule = agent.Scene.RequestModuleInterface <IAttachmentsModule>(); if (attModule != null) { attModule.ValidateAttachments(agent.UUID); } int xOffset = crossingRegion.RegionLocX - m_scene.RegionInfo.RegionLocX; int yOffset = crossingRegion.RegionLocY - m_scene.RegionInfo.RegionLocY; if (xOffset < 0) { pos.X += m_scene.RegionInfo.RegionSizeX; } else if (xOffset > 0) { pos.X -= m_scene.RegionInfo.RegionSizeX; } if (yOffset < 0) { pos.Y += m_scene.RegionInfo.RegionSizeY; } else if (yOffset > 0) { pos.Y -= m_scene.RegionInfo.RegionSizeY; } //Make sure that they are within bounds (velocity can push it out of bounds) if (pos.X < 0) { pos.X = 1; } if (pos.Y < 0) { pos.Y = 1; } if (pos.X > crossingRegion.RegionSizeX) { pos.X = crossingRegion.RegionSizeX - 1; } if (pos.Y > crossingRegion.RegionSizeY) { pos.Y = crossingRegion.RegionSizeY - 1; } AgentData cAgent = new AgentData(); agent.CopyTo(cAgent); cAgent.Position = pos; if (isFlying) { cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; } AgentCircuitData agentCircuit = agent.ControllingClient.RequestClientInfo(); agentCircuit.startpos = pos; agentCircuit.child = false; IAvatarAppearanceModule appearance = agent.RequestModuleInterface <IAvatarAppearanceModule> (); if (appearance != null) { agentCircuit.Appearance = appearance.Appearance; } IEventQueueService eq = agent.Scene.RequestModuleInterface <IEventQueueService>(); if (eq != null) { //This does UpdateAgent and closing of child agents // messages if they need to be called ISyncMessagePosterService syncPoster = agent.Scene.RequestModuleInterface <ISyncMessagePosterService>(); if (syncPoster != null) { OSDMap map = syncPoster.Get(SyncMessageHelper.CrossAgent(crossingRegion, pos, agent.Velocity, agentCircuit, cAgent, agent.Scene.RegionInfo.RegionHandle), agent.Scene.RegionInfo.RegionHandle); bool result = map["Success"].AsBoolean(); if (!result) { agent.ControllingClient.SendTeleportFailed(map["Reason"].AsString()); return(agent); } } } agent.MakeChildAgent(); //Revolution- We already were in this region... we don't need updates about the avatars we already know about, right? // OLD: now we have a child agent in this region. Request and send all interesting data about (root) agents in the sim //agent.SendOtherAgentsAvatarDataToMe(); //agent.SendOtherAgentsAppearanceToMe(); //Kill the groups here, otherwise they will become ghost attachments // and stay in the sim, they'll get readded below into the new sim KillAttachments(agent); } return(agent); }
/// <summary> /// Attach the object to the avatar /// </summary> /// <param name="remoteClient">The client that is having the attachment done</param> /// <param name="localID">The localID (SceneObjectPart) that is being attached (for the attach script event)</param> /// <param name="group">The group (SceneObjectGroup) that is being attached</param> /// <param name="AttachmentPt">The point to where the attachment will go</param> /// <param name="assetID" /> /// <param name="forceUpdatePrim">Force updating of the prim the next time the user attempts to deattach it</param> /// <param name="isTempAttach">Is a temporary attachment</param> protected void FindAttachmentPoint(IClientAPI remoteClient, uint localID, ISceneEntity group, int AttachmentPt, UUID assetID, bool forceUpdatePrim, bool isTempAttach) { //Make sure that we arn't over the limit of attachments ISceneEntity[] attachments = GetAttachmentsForAvatar(remoteClient.AgentId); if (attachments.Length + 1 > m_maxNumberOfAttachments) { //Too many remoteClient.SendAgentAlertMessage( "You are wearing too many attachments. Take one off to attach this object", false); return; } Vector3 attachPos = group.GetAttachmentPos(); bool hasMultipleAttachmentsSet = (AttachmentPt & 0x7f) != 0 || AttachmentPt == 0; if (!m_allowMultipleAttachments) { hasMultipleAttachmentsSet = false; } AttachmentPt &= 0x7f; //Disable it! Its evil! //Did the attachment change position or attachment point? bool changedPositionPoint = false; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. //Simplier terms: the attachment point changed, set it to the default 0,0,0 location if (AttachmentPt != 0 && AttachmentPt != (group.GetAttachmentPoint() & 0x7f)) { attachPos = Vector3.Zero; changedPositionPoint = true; } else { // AttachmentPt 0 means the client chose to 'wear' the attachment. if (AttachmentPt == 0) { // Check object for stored attachment point AttachmentPt = group.GetSavedAttachmentPoint() & 0x7f; attachPos = group.GetAttachmentPos(); } //Check state afterwards... use the newer GetSavedAttachmentPoint and Pos above first if (AttachmentPt == 0) { // Check object for older stored attachment point AttachmentPt = group.RootChild.Shape.State & 0x7f; } // if we still didn't find a suitable attachment point, force it to the default //This happens on the first time an avatar 'wears' an object if (AttachmentPt == 0) { // Stick it on right hand with Zero Offset from the attachment point. AttachmentPt = (int)AttachmentPoint.RightHand; //Default location attachPos = Vector3.Zero; changedPositionPoint = true; } } MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2} localID {3}", group.Name, remoteClient.Name, AttachmentPt, group.LocalId); //Update where we are put group.SetAttachmentPoint((byte)AttachmentPt); //Fix the position with the one we found group.AbsolutePosition = attachPos; // Remove any previous attachments IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence == null) { return; } UUID itemID = UUID.Zero; //Check for multiple attachment bits and whether we should remove the old if (!hasMultipleAttachmentsSet) { foreach (ISceneEntity grp in attachments) { if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { itemID = grp.RootChild.FromUserInventoryItemID; break; } } if (itemID != UUID.Zero) { DetachSingleAttachmentToInventory(itemID, remoteClient); } } itemID = group.RootChild.FromUserInventoryItemID; group.RootChild.AttachedAvatar = presence.UUID; List <ISceneChildEntity> parts = group.ChildrenEntities(); foreach (ISceneChildEntity t in parts) { t.AttachedAvatar = presence.UUID; } if (group.RootChild.PhysActor != null) { m_scene.PhysicsScene.DeletePrim(group.RootChild.PhysActor); group.RootChild.PhysActor = null; } group.RootChild.AttachedPos = attachPos; group.RootChild.IsAttachment = true; group.AbsolutePosition = attachPos; group.RootChild.SetParentLocalId(presence.LocalId); group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below if (group.IsSelected) { foreach (ISceneChildEntity part in group.ChildrenEntities()) { part.CreateSelected = true; } } //NOTE: This MUST be here, otherwise we limit full updates during attachments when they are selected and it will block the first update. // So until that is changed, this MUST stay. The client will instantly reselect it, so this value doesn't stay borked for long. group.IsSelected = false; if (!isTempAttach) { if (itemID == UUID.Zero) { //Delete the object inworld to inventory List <ISceneEntity> groups = new List <ISceneEntity>(1) { group }; IInventoryAccessModule inventoryAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (inventoryAccess != null) { inventoryAccess.DeleteToInventory(DeRezAction.AcquireToUserInventory, UUID.Zero, groups, remoteClient.AgentId, out itemID); } } else { //it came from an item, we need to start the scripts // Fire after attach, so we don't get messy perms dialogs. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); } if (UUID.Zero == itemID) { MainConsole.Instance.Error( "[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID."); remoteClient.SendAgentAlertMessage( "Unable to save attachment. Error inventory item ID.", false); return; } // XXYY!! if (assetID == UUID.Zero) { assetID = m_scene.InventoryService.GetItemAssetID(remoteClient.AgentId, itemID); //Update the ItemID with the new item group.SetFromItemID(itemID, assetID); } } else { // Fire after attach, so we don't get messy perms dialogs. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); group.RootChild.FromUserInventoryItemID = UUID.Zero; } AvatarAttachments attPlugin = presence.RequestModuleInterface <AvatarAttachments>(); if (attPlugin != null) { attPlugin.AddAttachment(group); presence.SetAttachments(attPlugin.Get()); if (!isTempAttach) { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); appearance.Appearance.SetAttachments(attPlugin.Get()); AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); } } // In case it is later dropped again, don't let // it get cleaned up group.RootChild.RemFlag(PrimFlags.TemporaryOnRez); group.HasGroupChanged = changedPositionPoint || forceUpdatePrim; //Now recreate it so that it is selected group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); m_scene.EventManager.TriggerOnAttach(localID, group.RootChild.FromUserInventoryItemID, remoteClient.AgentId); }
/// <summary> /// Update what the avatar is wearing using an item from their inventory. /// </summary> /// <param name="client"></param> /// <param name="e"></param> public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e) { IScenePresence sp = m_scene.GetScenePresence(client.AgentId); var agentName = GetAgentName(client.AgentId); if (sp == null) { MainConsole.Instance.WarnFormat("[AvatarFactory]: AvatarIsWearing unable to find presence for {0}", agentName); return; } MainConsole.Instance.DebugFormat("[AvatarFactory]: AvatarIsWearing called for {0}", agentName); // operate on a copy of the appearance so we don't have to lock anything IAvatarAppearanceModule appearance = sp.RequestModuleInterface <IAvatarAppearanceModule> (); AvatarAppearance avatAppearance = new AvatarAppearance(appearance.Appearance, false); #region Teen Mode Stuff IOpenRegionSettingsModule module = m_scene.RequestModuleInterface <IOpenRegionSettingsModule> (); bool NeedsRebake = false; if (module != null && module.EnableTeenMode) { foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) { if (wear.Type == 10 & wear.ItemID == UUID.Zero && module.DefaultUnderpants != UUID.Zero) { NeedsRebake = true; wear.ItemID = module.DefaultUnderpants; InventoryItemBase item = new InventoryItemBase(UUID.Random()) { InvType = (int)InventoryType.Wearable, AssetType = (int)AssetType.Clothing, Name = "Default Underpants", Folder = m_scene.InventoryService.GetFolderForType(client.AgentId, InventoryType.Wearable, FolderType.Clothing).ID, Owner = client.AgentId, CurrentPermissions = 0, CreatorId = UUID.Zero.ToString(), AssetID = module.DefaultUnderpants }; // Locked client.SendInventoryItemCreateUpdate(item, 0); } else if (wear.Type == 10 & wear.ItemID == UUID.Zero) { NeedsRebake = true; InventoryItemBase item = new InventoryItemBase(UUID.Random()) { InvType = (int)InventoryType.Wearable, AssetType = (int)AssetType.Clothing, Name = "Default Underpants", Folder = m_scene.InventoryService.GetFolderForType(client.AgentId, InventoryType.Wearable, FolderType.Clothing).ID, Owner = client.AgentId, CurrentPermissions = 0 }; // Locked if (m_underPantsUUID == UUID.Zero) { m_underPantsUUID = UUID.Random(); AssetBase asset = new AssetBase(m_underPantsUUID, "Default Underpants", AssetType.Clothing, UUID.Zero) { Data = Utils.StringToBytes(m_defaultUnderPants) }; asset.ID = m_scene.AssetService.Store(asset); m_underPantsUUID = asset.ID; } item.CreatorId = UUID.Zero.ToString(); item.AssetID = m_underPantsUUID; m_scene.InventoryService.AddItemAsync(item, null); client.SendInventoryItemCreateUpdate(item, 0); wear.ItemID = item.ID; } if (wear.Type == 11 && wear.ItemID == UUID.Zero && module.DefaultUndershirt != UUID.Zero) { NeedsRebake = true; wear.ItemID = module.DefaultUndershirt; InventoryItemBase item = new InventoryItemBase(UUID.Random()) { InvType = (int)InventoryType.Wearable, AssetType = (int)AssetType.Clothing, Name = "Default Undershirt", Folder = m_scene.InventoryService.GetFolderForType(client.AgentId, InventoryType.Wearable, FolderType.Clothing).ID, Owner = client.AgentId, CurrentPermissions = 0, CreatorId = UUID.Zero.ToString(), AssetID = module.DefaultUndershirt }; // Locked client.SendInventoryItemCreateUpdate(item, 0); } else if (wear.Type == 11 & wear.ItemID == UUID.Zero) { NeedsRebake = true; InventoryItemBase item = new InventoryItemBase(UUID.Random()) { InvType = (int)InventoryType.Wearable, AssetType = (int)AssetType.Clothing, Name = "Default Undershirt", Folder = m_scene.InventoryService.GetFolderForType(client.AgentId, InventoryType.Wearable, FolderType.Clothing).ID, Owner = client.AgentId, CurrentPermissions = 0 }; //Locked if (m_underShirtUUID == UUID.Zero) { m_underShirtUUID = UUID.Random(); AssetBase asset = new AssetBase(m_underShirtUUID, "Default Undershirt", AssetType.Clothing, UUID.Zero) { Data = Utils.StringToBytes(m_defaultUnderShirt) }; asset.ID = m_scene.AssetService.Store(asset); m_underShirtUUID = asset.ID; } item.CreatorId = UUID.Zero.ToString(); item.AssetID = m_underShirtUUID; m_scene.InventoryService.AddItemAsync(item, null); client.SendInventoryItemCreateUpdate(item, 0); wear.ItemID = item.ID; } } } #endregion foreach ( AvatarWearingArgs.Wearable wear in e.NowWearing.Where(wear => wear.Type < AvatarWearable.MAX_WEARABLES)) { avatAppearance.Wearables [wear.Type].Add(wear.ItemID, UUID.Zero); } avatAppearance.GetAssetsFrom(appearance.Appearance); // This could take awhile since it needs to pull inventory SetAppearanceAssets(sp.UUID, e.NowWearing, appearance.Appearance, ref avatAppearance); // could get fancier with the locks here, but in the spirit of "last write wins" // this should work correctly, also, we don't need to send the appearance here // since the "iswearing" will trigger a new set of visual param and baked texture changes // when those complete, the new appearance will be sent appearance.Appearance = avatAppearance; //This only occurs if something has been forced on afterwards (teen mode stuff) if (NeedsRebake) { //Tell the client about the new things it is wearing sp.ControllingClient.SendWearables(appearance.Appearance.Wearables, appearance.Appearance.Serial); //Then forcefully tell it to rebake foreach ( Primitive.TextureEntryFace face in appearance.Appearance.Texture.FaceTextures.Select(t => (t)).Where(face => face != null)) { sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID); } } QueueAppearanceSave(sp.UUID); //Send the wearables HERE so that the client knows what it is wearing //sp.ControllingClient.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial); //Do not save or send the appearance! The client loops back and sends a bunch of SetAppearance // (handled above) and that takes care of it }
protected void HandleSaveAvatarArchive(string module, string[] cmdparams) { if (cmdparams.Length != 7) { m_log.Info("[AvatarArchive] Not enough parameters!"); } UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, cmdparams[3] + " " + cmdparams[4]); if (account == null) { m_log.Error("[AvatarArchive] User not found!"); return; } IScenePresence SP; m_scene.TryGetScenePresence(account.PrincipalID, out SP); if (SP == null) { return; //Bad people! } SP.ControllingClient.SendAlertMessage("Appearance saving in progress..."); AvatarAppearance appearance = AvatarService.GetAppearance(SP.UUID); if (appearance == null) { IAvatarAppearanceModule appearancemod = SP.RequestModuleInterface <IAvatarAppearanceModule> (); appearance = appearancemod.Appearance; } StreamWriter writer = new StreamWriter(cmdparams[5], false); OSDMap map = new OSDMap(); OSDMap body = new OSDMap(); OSDMap assets = new OSDMap(); OSDMap items = new OSDMap(); body = appearance.Pack(); body.Add("FolderName", OSD.FromString(cmdparams[6])); foreach (AvatarWearable wear in appearance.Wearables) { for (int i = 0; i < wear.Count; i++) { WearableItem w = wear[i]; if (w.AssetID != UUID.Zero) { SaveItem(w.ItemID, items, assets); SaveAsset(w.AssetID, assets); } } } List <AvatarAttachment> attachments = appearance.GetAttachments(); foreach (AvatarAttachment a in attachments) { if (a.AssetID != UUID.Zero) { SaveItem(a.ItemID, items, assets); SaveAsset(a.AssetID, assets); } } map.Add("Body", body); map.Add("Assets", assets); map.Add("Items", items); //Write the map writer.Write(OSDParser.SerializeLLSDXmlString(map)); writer.Close(); writer.Dispose(); m_log.Info("[AvatarArchive] Saved archive to " + cmdparams[5]); }
/// <summary> /// Creates a new bot inworld /// </summary> /// <param name = "FirstName"></param> /// <param name = "LastName"></param> /// <param name = "cloneAppearanceFrom">UUID of the avatar whos appearance will be copied to give this bot an appearance</param> /// <returns>ID of the bot</returns> public UUID CreateAvatar(string FirstName, string LastName, IScene scene, UUID cloneAppearanceFrom, UUID creatorID, Vector3 startPos) { AgentCircuitData m_aCircuitData = new AgentCircuitData { child = false, circuitcode = (uint)Util.RandomClass.Next(), Appearance = GetAppearance(cloneAppearanceFrom, scene) }; //Add the circuit data so they can login //Sets up appearance if (m_aCircuitData.Appearance == null) { m_aCircuitData.Appearance = new AvatarAppearance { Wearables = AvatarWearable.DefaultWearables }; } //Create the new bot data BotClientAPI m_character = new BotClientAPI(scene, m_aCircuitData) { FirstName = FirstName, LastName = LastName }; m_aCircuitData.AgentID = m_character.AgentId; m_aCircuitData.Appearance.Owner = m_character.AgentId; List <AvatarAttachment> attachments = m_aCircuitData.Appearance.GetAttachments(); m_aCircuitData.Appearance.ClearAttachments(); foreach (AvatarAttachment t in attachments) { InventoryItemBase item = scene.InventoryService.GetItem(new InventoryItemBase(t.ItemID)); if (item != null) { item.ID = UUID.Random(); item.Owner = m_character.AgentId; item.Folder = UUID.Zero; scene.InventoryService.AddItemAsync(item, null); //Now fix the ItemID m_aCircuitData.Appearance.SetAttachment(t.AttachPoint, item.ID, t.AssetID); } } scene.AuthenticateHandler.AgentCircuits.Add(m_character.CircuitCode, m_aCircuitData); //This adds them to the scene and sets them inworld AddAndWaitUntilAgentIsAdded(scene, m_character); IScenePresence SP = scene.GetScenePresence(m_character.AgentId); if (SP == null) { return(UUID.Zero); //Failed! } Bot bot = new Bot(); bot.Initialize(SP, creatorID); SP.MakeRootAgent(startPos, false, true); //Move them SP.Teleport(startPos); foreach (var presence in scene.GetScenePresences()) { presence.SceneViewer.QueuePresenceForUpdate(SP, PrimUpdateFlags.ForcedFullUpdate); } IAttachmentsModule attModule = SP.Scene.RequestModuleInterface <IAttachmentsModule>(); if (attModule != null) { foreach (AvatarAttachment att in attachments) { attModule.RezSingleAttachmentFromInventory(SP.ControllingClient, att.ItemID, att.AssetID, 0, true); } } IAvatarAppearanceModule appearance = SP.RequestModuleInterface <IAvatarAppearanceModule>(); appearance.InitialHasWearablesBeenSent = true; //Save them in the bots list m_bots.Add(m_character.AgentId, bot); AddTagToBot(m_character.AgentId, "AllBots", bot.AvatarCreatorID); MainConsole.Instance.Info("[RexBotManager]: Added bot " + m_character.Name + " to scene."); //Return their UUID return(m_character.AgentId); }
/// <summary> /// A partial implementation. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox /// So far only valid for standing/flying/ground sitting avatars and single prim objects. /// If the object has multiple prims and/or a sitting avatar then the bounding /// box is for the root prim only. /// </summary> public LSL_List llGetBoundingBox(string obj) { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return(new LSL_List()); } UUID objID = UUID.Zero; LSL_List result = new LSL_List(); if (!UUID.TryParse(obj, out objID)) { result.Add(new LSL_Vector()); result.Add(new LSL_Vector()); return(result); } IScenePresence presence = World.GetScenePresence(objID); if (presence != null) { if (presence.ParentID == UUID.Zero) // not sat on an object { LSL_Vector lower = new LSL_Vector(); LSL_Vector upper = new LSL_Vector(); if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { // This is for ground sitting avatars IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); if (appearance != null) { float height = appearance.Appearance.AvatarHeight / 2.66666667f; lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); } } else { // This is for standing/flying avatars IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); if (appearance != null) { float height = appearance.Appearance.AvatarHeight / 2.0f; lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); } } result.Add(lower); result.Add(upper); return(result); } // sitting on an object so we need the bounding box of that // which should include the avatar so set the UUID to the // UUID of the object the avatar is sat on and allow it to fall through // to processing an object ISceneChildEntity p = World.GetSceneObjectPart(presence.ParentID); objID = p.UUID; } ISceneChildEntity part = World.GetSceneObjectPart(objID); // Currently only works for single prims without a sitting avatar if (part != null) { Vector3 halfSize = part.Scale * 0.5f; LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); result.Add(lower); result.Add(upper); return(result); } // Not found so return empty values result.Add(new LSL_Vector()); result.Add(new LSL_Vector()); return(result); }