/// <summary>
        /// Move the next object in the queue to inventory.  Then delete it properly from the scene.
        /// </summary>
        /// <returns></returns>
        public bool InventoryDeQueueAndDelete()
        {
            DeleteToInventoryHolder x = null;

            try
            {
                lock (m_inventoryDeletes)
                {
                    int left = m_inventoryDeletes.Count;
                    if (left > 0)
                    {
                        x = m_inventoryDeletes.Dequeue();

                        m_log.DebugFormat(
                            "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left);

                        try
                        {
                            IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>();
                            if (invAccess != null)
                            {
                                invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient);
                            }
                            if (x.permissionToDelete)
                            {
                                foreach (SceneObjectGroup g in x.objectGroups)
                                {
                                    m_scene.DeleteSceneObject(g, false);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            m_log.ErrorFormat(
                                "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace);
                        }

                        return(true);
                    }
                }
            }
            catch (Exception e)
            {
                // We can't put the object group details in here since the root part may have disappeared (which is where these sit).
                // FIXME: This needs to be fixed.
                m_log.ErrorFormat(
                    "[ASYNC DELETER]: Queued sending of scene object to agent {0} {1} failed: {2} {3}",
                    (x != null ? x.remoteClient.Name : "unavailable"),
                    (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"),
                    e.Message,
                    e.StackTrace);
            }

            m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue.");

            return(false);
        }
Ejemplo n.º 2
0
        public bool DeleteObject()
        {
            DeleteToInventoryHolder x = null;

            try
            {
                if (m_removeFromSimQueue.TryDequeue(out x))
                {
                    MainConsole.Instance.DebugFormat(
                        "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.",
                        m_removeFromSimQueue.Count);

                    if (x.permissionToTake)
                    {
                        try
                        {
                            IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>();
                            UUID itemID;
                            if (invAccess != null)
                            {
                                invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.agentId, out itemID);
                            }
                        }
                        catch (Exception e)
                        {
                            MainConsole.Instance.ErrorFormat(
                                "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace);
                        }
                    }

                    //Moved Delete To After Object Taken To Inventory. Prevents script variables not being updated before taken to inventory
                    if (x.permissionToDelete)
                    {
                        IBackupModule backup = m_scene.RequestModuleInterface <IBackupModule>();
                        if (backup != null)
                        {
                            backup.DeleteSceneObjects(x.objectGroups.ToArray(), true, true);
                        }
                    }
                    return(true);
                }
            }
            catch (Exception e)
            {
                // We can't put the object group details in here since the root part may have disappeared (which is where these sit).
                // FIXME: This needs to be fixed.
                MainConsole.Instance.ErrorFormat(
                    "[SCENE]: Queued sending of scene object to agent {0} {1} failed: {2}",
                    (x != null ? x.agentId.ToString() : "unavailable"),
                    (x != null ? x.agentId.ToString() : "unavailable"), e);
            }

            //MainConsole.Instance.Debug("[SCENE]: No objects left in delete queue.");
            return(false);
        }
Ejemplo n.º 3
0
        /// <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);
        }