/// <summary>
        /// WARNING: This operation is asynchronous if the item is a script!
        /// Since removing a script from a prim's inventory is asynchronous, 
        /// replacing one requires the Add be performed in the Remove callback.
        /// This function is also used by RemoveInventoryItem (newItem==null).
        /// </summary>
        /// <param name="itemID">the item to replace or remove</param>
        /// <param name="replaceArgs">the new item to use to replace, or null on a Remove</param>
        /// <returns>Numeric asset type of the item removed.
        /// Returns -1 if the item did not exist in this prim's inventory.</returns>
        public int ReplaceInventoryItem(UUID itemID, bool allowedDrop, bool fireEvents, ReplaceItemArgs replaceArgs)
        {
            lock (m_items)
            {
                if (!m_items.ContainsKey(itemID))
                {
                    m_log.ErrorFormat(
                        "[PRIM INVENTORY]: " +
                        "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
                        itemID, m_part.Name, m_part.UUID);
                    return -1;
                }

                int type = m_items[itemID].InvType;
                if (type == 10) // Script
                {   
                    // _RemoveItem will be called asynchronously from the script engine thread
                    m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID, m_part, _ReplaceItem, replaceArgs, allowedDrop, fireEvents);
                    m_part.ParentGroup.AddActiveScriptCount(-1);
                }
                else
                {
                    // No scripts to wait for, remove the item right away.
                    _ReplaceItem(m_part, itemID, allowedDrop, fireEvents, replaceArgs);
                }
                return type;
            }
        }
        /// <summary>
        /// Called indirectly from EventManager.TriggerRemoveScript() once the script engine has 
        /// removed the script and the task item can be safely deleted.
        /// If replaceArgs is null, it's a remove, otherwise it's a replace (remove plus add).
        /// </summary>
        private void _ReplaceItem(SceneObjectPart part, UUID itemID, bool allowedDrop, bool fireEvents, ReplaceItemArgs replaceArgs)
        {
            TaskInventoryItem newItem = null;
            bool scriptUpdate = false;
            int type = m_items[itemID].InvType;
            if (type == 10) // Script
                scriptUpdate = true;
            if ((replaceArgs != null) && (replaceArgs.ReplacementItem != null))
                newItem = replaceArgs.ReplacementItem;

            m_items.Remove(itemID);
            _removedItems.Add(itemID);
            m_inventorySerial++;
            m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
            HasInventoryChanged = true;
            m_part.ParentGroup.HasGroupChanged = true;

            if (newItem != null)
            {
                // AddInventoryItem increments the serial and triggering the events
                AddInventoryItem(replaceArgs.ReplacementItem.Name, newItem, allowedDrop, fireEvents, null);
            }

            if (scriptUpdate)
            {
                HandleChangedScripts(newItem, replaceArgs);
            }
            m_part.ScheduleFullUpdate(PrimUpdateFlags.PrimFlags);
        }
        private void HandleChangedScripts(TaskInventoryItem newItem, ReplaceItemArgs replaceArgs)
        {
            int scriptcount = 0;
            foreach (TaskInventoryItem item in m_items.Values)
            {
                if ((InventoryType)item.Type == InventoryType.LSL)
                {
                    scriptcount++;
                }
            }

            if (scriptcount > 0)
                m_part.AddFlag(PrimFlags.Scripted);
            else
                m_part.RemFlag(PrimFlags.Scripted);

            // Update for loss of other events (e.g. money, touch)
            m_part.DoAggregateScriptEvents();

            if (replaceArgs != null)
            {
                Scene scene = m_part.ParentGroup.Scene;
                if (replaceArgs.Running > 0)
                {
                    m_part.Inventory.CreateScriptInstance(newItem, replaceArgs.StartParam, ScriptStartFlags.None, scene.DefaultScriptEngine, 0, null);
                }

                ScenePresence avatar;

                if (scene.TryGetAvatar(newItem.OwnerID, out avatar))
                {
                    m_part.GetProperties(avatar.ControllingClient);
                }
            }
        }
        /// <summary>
        /// Add an item to this prim's inventory.
        /// </summary>
        /// <param name="name">The name that the new item should have.</param>
        /// <param name="item">
        /// The item itself.  The name within this structure is ignored in favour of the name
        /// given in this method's arguments
        /// </param>
        /// <param name="allowedDrop">
        /// Item was only added to inventory because AllowedDrop is set
        /// </param>
        protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop, bool fireEvents, ReplaceItemArgs replaceArgs)
        {
            name = FindAvailableInventoryName(name);
            if (String.IsNullOrEmpty(name))
                return;

            item.ParentID = m_part.UUID;
            item.ParentPartID = m_part.UUID;
            item.Name = name;

            lock (m_items)
            {
                m_items.Add(item.ItemID, item);
            }

            if (fireEvents)
            {
                if (allowedDrop)
                    m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
                else
                    m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
            }

            m_inventorySerial++;
            //m_inventorySerial += 2;
            HasInventoryChanged = true;

            //may be parentless briefly while a copy is performed
            if (m_part.ParentGroup != null)
            {
                m_part.ParentGroup.HasGroupChanged = true;
            }

            // If called from AddReplaceInventoryItem (above), the script may be running, depending on
            // llRemoteLoadScriptPin params, so tie up the loose ends of adding a new running script.
            HandleChangedScripts(item, replaceArgs);
        }
        /// <summary>
        /// Add an item to this prim's inventory.  If an item with the same name already exists, it is replaced.
        /// </summary>
        /// <param name="item"></param>
        public void AddReplaceInventoryItem(TaskInventoryItem item, bool allowedDrop, bool fireEvents, ReplaceItemArgs replaceArgs)
        {
            List<TaskInventoryItem> il;

            lock (m_items)
            {
                il = new List<TaskInventoryItem>(m_items.Values);
            }

            foreach (TaskInventoryItem i in il)
            {
                if (i.Name == item.Name)
                {
                    ReplaceInventoryItem(i.ItemID, allowedDrop, fireEvents, replaceArgs);
                    return;        // found it, all done
                }
            }

            AddInventoryItem(item.Name, item, allowedDrop, fireEvents, replaceArgs);
        }
        /// <summary>
        /// Rez a script into a prim's inventory from another prim
        /// </summary>
        /// <param name="remoteClient"></param>
        /// <param name="itemID"> </param>
        /// <param name="localID"></param>
        /// <returns>Script error text to be reported, or empty string on success.</returns>
        public string RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param)
        {
            TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId);

            if (srcTaskItem == null)
            {
                m_log.ErrorFormat(
                    "[PRIM INVENTORY]: Tried to retrieve item ID {0} from prim {1}, {2} for rezzing a script but the "
                        + " item does not exist in this inventory",
                    srcId, srcPart.Name, srcPart.UUID);

                return "Could not find script to load.";
            }

            SceneObjectPart destPart = GetSceneObjectPart(destId);

            if (destPart == null)
            {
                m_log.ErrorFormat("[PRIM INVENTORY]: Could not find target part {0} to load script into.", destId);
                return "Could not find target prim to load script.";
            }
        
            // Must own the object, and have modify rights
            if (srcPart.OwnerID != destPart.OwnerID)
            {
                // Group permissions
                if ( (destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) ||
                ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0) )
                    return "Ownership mismatch or lack of Modify permission.";
            } else {
                if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
                    return "Destination lacks Modify permission.";
            }

            if ((destPart.ScriptAccessPin == 0) || (destPart.ScriptAccessPin != pin))
            {
                m_log.WarnFormat(
                        "[PRIM INVENTORY]: " +
                        "Script in object {0} : {1}, attempted to load script {2} : {3} into object {4} : {5} with invalid pin {6}",
                        srcPart.Name, srcId, srcTaskItem.Name, srcTaskItem.ItemID, destPart.Name, destId, pin);
				if (destPart.ScriptAccessPin == 0) {
					return "NO PIN";
				}
                return "PIN";   // signal a different response to the caller
            }

            TaskInventoryItem destTaskItem = new TaskInventoryItem();

            destTaskItem.ItemID = UUID.Random();
            destTaskItem.CreatorID = srcTaskItem.CreatorID;
            destTaskItem.AssetID = srcTaskItem.AssetID;
            destTaskItem.GroupID = destPart.GroupID;
            destTaskItem.OwnerID = destPart.OwnerID;
            destTaskItem.ParentID = destPart.UUID;
            destTaskItem.ParentPartID = destPart.UUID;

            destTaskItem.BasePermissions = srcTaskItem.BasePermissions;
            destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions;
            destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions;
            destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions;
            destTaskItem.NextPermissions = srcTaskItem.NextPermissions;
            destTaskItem.Flags = srcTaskItem.Flags;

            if (destPart.OwnerID != srcPart.OwnerID)
            {
                if (Permissions.PropagatePermissions())
                {
                    destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions &
                            srcTaskItem.NextPermissions;
                    destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions &
                            srcTaskItem.NextPermissions;
                    destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions &
                            srcTaskItem.NextPermissions;
                    destTaskItem.BasePermissions = srcTaskItem.BasePermissions &
                            srcTaskItem.NextPermissions;
                    if (destTaskItem.InvType == (int)InventoryType.Object)
                    {
                        destTaskItem.CurrentPermissions |= ScenePermBits.SLAM;            // Slam!
                        destTaskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;    // Tell the viewer we are going to slam this
                    }
                }
            }

            destTaskItem.Description = srcTaskItem.Description;
            destTaskItem.Name = srcTaskItem.Name;
            destTaskItem.InvType = srcTaskItem.InvType;
            destTaskItem.Type = srcTaskItem.Type;

            // WARNING: This operation is asynchronous if the item is a script! Careful what occurs after this.
            ReplaceItemArgs replaceArgs = new ReplaceItemArgs(destTaskItem, running, start_param);
            destPart.Inventory.AddReplaceInventoryItem(destTaskItem, false, true, replaceArgs);

            return String.Empty;    // success, no error
        }
Example #7
0
 void EventManager_OnRemoveScript(uint localID, OpenMetaverse.UUID itemID, SceneObjectPart part, EventManager.ScriptPostUnloadDelegate callback, bool allowedDrop, bool fireEvents, ReplaceItemArgs replaceArgs)
 {
     _scriptLoader.PostLoadUnloadRequest(
         new LoadUnloadRequest
         {
             RequestType = LoadUnloadRequest.LUType.Unload,
             LocalId = localID,
             PostUnloadCallback = callback,
             CallbackParams = new LoadUnloadRequest.UnloadCallbackParams
             {
                 Prim = part,
                 ItemId = itemID,
                 AllowedDrop = allowedDrop,
                 FireEvents = fireEvents,
                 ReplaceArgs = replaceArgs,
             }
         });
 }
Example #8
0
 // This method can either remove a script or replace it with a new one.
 // If replaceArgs is null, it's a Remove and remaining parameters ignored.
 // If replaceArgs is not null, it's a Remove + Add(replaceArgs, allowedDrop, fireEvents).
 public void TriggerRemoveScript(uint localID, UUID itemID, SceneObjectPart part, ScriptPostUnloadDelegate callback, ReplaceItemArgs replaceArgs, bool allowDrop, bool fireEvents)
 {
     handlerRemoveScript = OnRemoveScript;
     if (handlerRemoveScript != null)
     {
         handlerRemoveScript(localID, itemID, part, callback, allowDrop, fireEvents, replaceArgs);
     }
 }