From 7bb005b0d1a5ae63ca94a3a3f8ad98e0388ea76b Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 16 Nov 2010 21:01:56 +0000 Subject: Change the way attachments are persisted. Editing a worn attachment will now save properly, as will the results of a resizer script working. Attachment positions are no longer saved on each move, but instead are saved once on logout. Attachment script states are saved as part of the attachment now when detaching. --- .../Avatar/Attachments/AttachmentsModule.cs | 34 +++++++----------- .../InventoryAccess/InventoryAccessModule.cs | 18 +++++++--- .../Framework/Interfaces/IAttachmentsModule.cs | 21 ++++++++---- .../Framework/Interfaces/IEntityInventory.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 17 ++++++--- .../Region/Framework/Scenes/SceneObjectGroup.cs | 6 ++-- .../Framework/Scenes/SceneObjectPartInventory.cs | 40 ++++++++++++---------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 20 +++++++++++ 9 files changed, 101 insertions(+), 60 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 348b8b9..1744fb3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -273,6 +273,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (objatt != null) { + // Loading the inventory from XML will have set this, but + // there is no way the object could have changed yet, + // since scripts aren't running yet. So, clear it here. + objatt.HasGroupChanged = false; bool tainted = false; if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; @@ -470,6 +474,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); group.DetachToInventoryPrep(); m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); + + // If an item contains scripts, it's always changed. + // This ensures script state is saved on detach + foreach (SceneObjectPart p in group.Parts) + if (p.Inventory.ContainsScripts()) + group.HasGroupChanged = true; + UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID); m_scene.DeleteSceneObject(group, false); return; @@ -478,25 +489,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } - public void UpdateAttachmentPosition(IClientAPI client, SceneObjectGroup sog, Vector3 pos) - { - // If this is an attachment, then we need to save the modified - // object back into the avatar's inventory. First we save the - // attachment point information, then we update the relative - // positioning (which caused this method to get driven in the - // first place. Then we have to mark the object as NOT an - // attachment. This is necessary in order to correctly save - // and retrieve GroupPosition information for the attachment. - // Then we save the asset back into the appropriate inventory - // entry. Finally, we restore the object's attachment status. - byte attachmentPoint = sog.GetAttachmentPoint(); - sog.UpdateGroupPosition(pos); - sog.RootPart.IsAttachment = false; - sog.AbsolutePosition = sog.RootPart.AttachedPos; - UpdateKnownItem(client, sog, sog.GetFromItemID(), sog.OwnerID); - sog.SetAttachmentPoint(attachmentPoint); - } - /// /// Update the attachment asset for the new sog details if they have changed. /// @@ -508,7 +500,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// - protected void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) + public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) { if (grp != null) { @@ -523,7 +515,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments grp.UUID, grp.GetAttachmentPoint()); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); @@ -617,7 +608,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // In case it is later dropped again, don't let // it get cleaned up so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); - so.HasGroupChanged = false; } } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 7a175ea..ef21834 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -569,12 +569,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { group.RootPart.Flags |= PrimFlags.Phantom; group.RootPart.IsAttachment = true; - } - // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since - // we'll be doing that later on. Scheduling more than one full update during the attachment - // process causes some clients to fail to display the attachment properly. - m_Scene.AddNewSceneObject(group, true, false); + // If we're rezzing an attachment then don't ask + // AddNewSceneObject() to update the client since + // we'll be doing that later on. Scheduling more + // than one full update during the attachment + // process causes some clients to fail to display + // the attachment properly. + // Also, don't persist attachments. + m_Scene.AddNewSceneObject(group, false, false); + } + else + { + m_Scene.AddNewSceneObject(group, true, false); + } // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 24e481b..b3576c5 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -122,11 +122,20 @@ namespace OpenSim.Region.Framework.Interfaces void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); /// - /// Update the position of an attachment + /// Update the user inventory with a changed attachment /// - /// - /// - /// - void UpdateAttachmentPosition(IClientAPI client, SceneObjectGroup sog, Vector3 pos); + /// + /// A + /// + /// + /// A + /// + /// + /// A + /// + /// + /// A + /// + void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID); } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 2e6faa0..64664ab 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -183,6 +183,7 @@ namespace OpenSim.Region.Framework.Interfaces /// false if the item did not exist, true if the update occurred successfully bool UpdateInventoryItem(TaskInventoryItem item); bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents); + bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged); /// /// Remove an item from this entity's inventory diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a4cc66d..96a9f99 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3152,7 +3152,6 @@ namespace OpenSim.Region.Framework.Scenes List regions = new List(avatar.KnownChildRegionHandles); regions.Remove(RegionInfo.RegionHandle); m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); - } m_eventManager.TriggerClientClosed(agentID, this); } @@ -3164,6 +3163,9 @@ namespace OpenSim.Region.Framework.Scenes m_eventManager.TriggerOnRemovePresence(agentID); + if (avatar != null && (!avatar.IsChildAgent)) + avatar.SaveChangedAttachments(); + ForEachClient( delegate(IClientAPI client) { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 24d7334..032c859 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -259,7 +259,7 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - if (!alreadyPersisted) + if (attachToBackup && (!alreadyPersisted)) { sceneObject.ForceInventoryPersistence(); sceneObject.HasGroupChanged = true; @@ -282,8 +282,10 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { - // Ensure that we persist this new scene object - sceneObject.HasGroupChanged = true; + // Ensure that we persist this new scene object if it's not an + // attachment + if (attachToBackup) + sceneObject.HasGroupChanged = true; return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } @@ -1279,8 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes { if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) { - if (m_parentScene.AttachmentsModule != null) - m_parentScene.AttachmentsModule.UpdateAttachmentPosition(remoteClient, group, pos); + // Set the new attachment point data in the object + byte attachmentPoint = group.GetAttachmentPoint(); + group.UpdateGroupPosition(pos); + group.RootPart.IsAttachment = false; + group.AbsolutePosition = group.RootPart.AttachedPos; + group.SetAttachmentPoint(attachmentPoint); + group.HasGroupChanged = true; } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5f00f84..c2810b2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -491,13 +491,15 @@ namespace OpenSim.Region.Framework.Scenes XmlNodeList nodes = doc.GetElementsByTagName("SavedScriptState"); if (nodes.Count > 0) { - m_savedScriptState = new Dictionary(); + if (m_savedScriptState == null) + m_savedScriptState = new Dictionary(); foreach (XmlNode node in nodes) { if (node.Attributes["UUID"] != null) { UUID itemid = new UUID(node.Attributes["UUID"].Value); - m_savedScriptState.Add(itemid, node.InnerXml); + if (itemid != UUID.Zero) + m_savedScriptState[itemid] = node.InnerXml; } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 0c5e62d..6a204c3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -127,8 +127,6 @@ namespace OpenSim.Region.Framework.Scenes if (0 == m_items.Count) return; - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; IList items = GetInventoryItems(); m_items.Clear(); @@ -144,17 +142,6 @@ namespace OpenSim.Region.Framework.Scenes { lock (Items) { - if (Items.Count == 0) - { - return; - } - - HasInventoryChanged = true; - if (m_part.ParentGroup != null) - { - m_part.ParentGroup.HasGroupChanged = true; - } - IList items = new List(Items.Values); Items.Clear(); @@ -208,8 +195,15 @@ namespace OpenSim.Region.Framework.Scenes } } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; + // Don't let this set the HasGroupChanged flag for attachments + // as this happens during rez and we don't want a new asset + // for each attachment each time + if (!m_part.ParentGroup.RootPart.IsAttachment) + { + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + } + List items = GetInventoryItems(); foreach (TaskInventoryItem item in items) { @@ -674,13 +668,19 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred successfully public bool UpdateInventoryItem(TaskInventoryItem item) { - return UpdateInventoryItem(item, true); + return UpdateInventoryItem(item, true, true); } public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents) { + return UpdateInventoryItem(item, fireScriptEvents, true); + } + + public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) + { TaskInventoryItem it = GetInventoryItem(item.ItemID); if (it != null) + { item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; @@ -702,9 +702,11 @@ namespace OpenSim.Region.Framework.Scenes if (fireScriptEvents) m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; + if (considerChanged) + { + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + } return true; } else diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 34d1c39..bfc1bd6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3746,5 +3746,25 @@ namespace OpenSim.Region.Framework.Scenes m_reprioritization_called = false; } } + + public void SaveChangedAttachments() + { + // Need to copy this list because DetachToInventoryPrep mods it + List attachments = new List(Attachments.ToArray()); + + IAttachmentsModule attachmentsModule = m_scene.AttachmentsModule; + if (attachmentsModule != null) + { + foreach (SceneObjectGroup grp in attachments) + { + if (grp.HasGroupChanged) // Resizer scripts? + { + grp.DetachToInventoryPrep(); + attachmentsModule.UpdateKnownItem(ControllingClient, + grp, grp.GetFromItemID(), grp.OwnerID); + } + } + } + } } } -- cgit v1.1