diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index eccf7a6977..efab6ed5ff 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -211,16 +211,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments lock (sp.AttachmentsSyncLock) { - foreach (SceneObjectGroup grp in sp.GetAttachments()) + foreach (SceneObjectGroup so in sp.GetAttachments()) { - grp.Scene.DeleteSceneObject(grp, false); + // We can only remove the script instances from the script engine after we've retrieved their xml state + // when we update the attachment item. + m_scene.DeleteSceneObject(so, false, false); if (saveChanged || saveAllScripted) { - grp.IsAttachment = false; - grp.AbsolutePosition = grp.RootPart.AttachedPos; - UpdateKnownItem(sp, grp, saveAllScripted); + so.IsAttachment = false; + so.AbsolutePosition = so.RootPart.AttachedPos; + UpdateKnownItem(sp, so, saveAllScripted); } + + so.RemoveScriptInstances(true); } sp.ClearAttachments(); @@ -682,7 +686,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); sp.RemoveAttachment(so); - m_scene.DeleteSceneObject(so, false); + + // We can only remove the script instances from the script engine after we've retrieved their xml state + // when we update the attachment item. + m_scene.DeleteSceneObject(so, false, false); // Prepare sog for storage so.AttachedAvatar = UUID.Zero; @@ -691,6 +698,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.AbsolutePosition = so.RootPart.AttachedPos; UpdateKnownItem(sp, so, true); + so.RemoveScriptInstances(true); } private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 1c9bdce832..8d6284739b 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces void ResumeScripts(); /// - /// Stop all the scripts in this entity. + /// Stop and remove all the scripts in this entity from the scene. /// /// /// Should be true if these scripts are being removed because the scene @@ -100,6 +100,11 @@ namespace OpenSim.Region.Framework.Interfaces /// void RemoveScriptInstances(bool sceneObjectBeingDeleted); + /// + /// Stop all the scripts in this entity. + /// + void StopScriptInstances(); + /// /// Start a script which is in this entity's inventory. /// @@ -129,7 +134,7 @@ namespace OpenSim.Region.Framework.Interfaces bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); /// - /// Stop a script which is in this prim's inventory. + /// Stop and remove a script which is in this prim's inventory from the scene. /// /// /// @@ -138,6 +143,12 @@ namespace OpenSim.Region.Framework.Interfaces /// void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted); + /// + /// Stop a script which is in this prim's inventory. + /// + /// + void StopScriptInstance(UUID itemId); + /// /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// name is chosen. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ec911a52d4..25223b95b3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2183,13 +2183,30 @@ namespace OpenSim.Region.Framework.Scenes /// /// Synchronously delete the given object from the scene. /// + /// + /// Scripts are also removed. + /// /// Object Id /// Suppress broadcasting changes to other clients. public void DeleteSceneObject(SceneObjectGroup group, bool silent) + { + DeleteSceneObject(group, silent, true); + } + + /// + /// Synchronously delete the given object from the scene. + /// + /// Object Id + /// Suppress broadcasting changes to other clients. + /// If true, then scripts are removed. If false, then they are only stopped. + public void DeleteSceneObject(SceneObjectGroup group, bool silent, bool removeScripts) { // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); - group.RemoveScriptInstances(true); + if (removeScripts) + group.RemoveScriptInstances(true); + else + group.StopScriptInstances(); SceneObjectPart[] partList = group.Parts; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 2866b546eb..ddf5da0ba4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Stop the scripts contained in all the prims in this group + /// Stop and remove the scripts contained in all the prims in this group /// /// /// Should be true if these scripts are being removed because the scene @@ -92,6 +92,14 @@ namespace OpenSim.Region.Framework.Scenes parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted); } + /// + /// Stop the scripts contained in all the prims in this group + /// + public void StopScriptInstances() + { + Array.ForEach(m_parts.GetArray(), p => p.Inventory.StopScriptInstances()); + } + /// /// Add an inventory item from a user's inventory to a prim in this scene object. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 866311a298..cf2ed1a802 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -280,7 +280,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Stop all the scripts in this prim. + /// Stop and remove all the scripts in this prim. /// /// /// Should be true if these scripts are being removed because the scene @@ -293,6 +293,14 @@ namespace OpenSim.Region.Framework.Scenes RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); } + /// + /// Stop all the scripts in this prim. + /// + public void StopScriptInstances() + { + GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i)); + } + /// /// Start a script which is in this prim's inventory. /// @@ -443,7 +451,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Stop a script which is in this prim's inventory. + /// Stop and remove a script which is in this prim's inventory. /// /// /// @@ -470,7 +478,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_log.ErrorFormat( + m_log.WarnFormat( "[PRIM INVENTORY]: " + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", itemId, m_part.Name, m_part.UUID, @@ -478,6 +486,51 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Stop a script which is in this prim's inventory. + /// + /// + /// + /// Should be true if this script is being removed because the scene + /// object is being deleted. This will prevent spurious updates to the client. + /// + public void StopScriptInstance(UUID itemId) + { + TaskInventoryItem scriptItem; + + lock (m_items) + m_items.TryGetValue(itemId, out scriptItem); + + if (scriptItem != null) + { + StopScriptInstance(scriptItem); + } + else + { + m_log.WarnFormat( + "[PRIM INVENTORY]: " + + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", + itemId, m_part.Name, m_part.UUID, + m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + } + } + + /// + /// Stop a script which is in this prim's inventory. + /// + /// + /// + /// Should be true if this script is being removed because the scene + /// object is being deleted. This will prevent spurious updates to the client. + /// + public void StopScriptInstance(TaskInventoryItem item) + { + m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); + + // At the moment, even stopped scripts are counted as active, which is probably wrong. +// m_part.ParentGroup.AddActiveScriptCount(-1); + } + /// /// Check if the inventory holds an item with a given name. ///