diff options
author | Melanie | 2012-07-23 21:08:02 +0200 |
---|---|---|
committer | Melanie | 2012-07-23 21:08:02 +0200 |
commit | 9e00e2ddecdafa489de0ae67b78cf6971e55fe80 (patch) | |
tree | d2a9fdc3424a7dca00a1612399b25a3db0ac76a5 | |
parent | Fix double-ping on logout by not sending a stop packet to the client (diff) | |
download | opensim-SC_OLD-9e00e2ddecdafa489de0ae67b78cf6971e55fe80.zip opensim-SC_OLD-9e00e2ddecdafa489de0ae67b78cf6971e55fe80.tar.gz opensim-SC_OLD-9e00e2ddecdafa489de0ae67b78cf6971e55fe80.tar.bz2 opensim-SC_OLD-9e00e2ddecdafa489de0ae67b78cf6971e55fe80.tar.xz |
Change attachment handling to remove object from the scene first as per
justincc's original work. Sample scripts before doing so. Also refactor some
crucial common code and eliminate parameters that were only ever used with
the same constant value.
5 files changed, 81 insertions, 42 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index f073c4a..31e8a2e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.IO; | ||
31 | using System.Xml; | 32 | using System.Xml; |
32 | using log4net; | 33 | using log4net; |
33 | using Mono.Addins; | 34 | using Mono.Addins; |
@@ -248,7 +249,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
248 | } | 249 | } |
249 | } | 250 | } |
250 | 251 | ||
251 | public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted) | 252 | public void DeRezAttachments(IScenePresence sp) |
252 | { | 253 | { |
253 | if (!Enabled) | 254 | if (!Enabled) |
254 | return; | 255 | return; |
@@ -259,18 +260,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
259 | { | 260 | { |
260 | foreach (SceneObjectGroup so in sp.GetAttachments()) | 261 | foreach (SceneObjectGroup so in sp.GetAttachments()) |
261 | { | 262 | { |
262 | // We can only remove the script instances from the script engine after we've retrieved their xml state | 263 | UpdateDetachedObject(sp, so); |
263 | // when we update the attachment item. | ||
264 | m_scene.DeleteSceneObject(so, false, false); | ||
265 | |||
266 | if (saveChanged || saveAllScripted) | ||
267 | { | ||
268 | so.IsAttachment = false; | ||
269 | so.AbsolutePosition = so.RootPart.AttachedPos; | ||
270 | UpdateKnownItem(sp, so, saveAllScripted); | ||
271 | } | ||
272 | |||
273 | so.RemoveScriptInstances(true); | ||
274 | } | 264 | } |
275 | 265 | ||
276 | sp.ClearAttachments(); | 266 | sp.ClearAttachments(); |
@@ -597,7 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
597 | /// <param name="sp"></param> | 587 | /// <param name="sp"></param> |
598 | /// <param name="grp"></param> | 588 | /// <param name="grp"></param> |
599 | /// <param name="saveAllScripted"></param> | 589 | /// <param name="saveAllScripted"></param> |
600 | private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) | 590 | private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) |
601 | { | 591 | { |
602 | // Saving attachments for NPCs messes them up for the real owner! | 592 | // Saving attachments for NPCs messes them up for the real owner! |
603 | INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); | 593 | INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); |
@@ -607,13 +597,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
607 | return; | 597 | return; |
608 | } | 598 | } |
609 | 599 | ||
610 | if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) | 600 | if (grp.HasGroupChanged) |
611 | { | 601 | { |
612 | // m_log.DebugFormat( | 602 | // m_log.DebugFormat( |
613 | // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", | 603 | // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", |
614 | // grp.UUID, grp.AttachmentPoint); | 604 | // grp.UUID, grp.AttachmentPoint); |
615 | 605 | ||
616 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); | 606 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); |
617 | 607 | ||
618 | InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); | 608 | InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); |
619 | item = m_scene.InventoryService.GetItem(item); | 609 | item = m_scene.InventoryService.GetItem(item); |
@@ -750,29 +740,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
750 | return newItem; | 740 | return newItem; |
751 | } | 741 | } |
752 | 742 | ||
753 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) | 743 | private string GetObjectScriptStates(SceneObjectGroup grp) |
754 | { | 744 | { |
755 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | 745 | using (StringWriter sw = new StringWriter()) |
746 | { | ||
747 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | ||
748 | { | ||
749 | grp.SaveScriptedState(writer); | ||
750 | } | ||
756 | 751 | ||
757 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | 752 | return sw.ToString(); |
758 | sp.RemoveAttachment(so); | 753 | } |
754 | } | ||
755 | |||
756 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) | ||
757 | { | ||
758 | // Don't save attachments for HG visitors, it | ||
759 | // messes up their inventory. When a HG visitor logs | ||
760 | // out on a foreign grid, their attachments will be | ||
761 | // reloaded in the state they were in when they left | ||
762 | // the home grid. This is best anyway as the visited | ||
763 | // grid may use an incompatible script engine. | ||
764 | bool saveChanged | ||
765 | = sp.PresenceType != PresenceType.Npc | ||
766 | && (m_scene.UserManagementModule == null | ||
767 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); | ||
768 | |||
769 | // Scripts MUST be snapshotted before the object is | ||
770 | // removed from the scene because doing otherwise will | ||
771 | // clobber the run flag | ||
772 | string scriptedState = GetObjectScriptStates(so); | ||
773 | |||
774 | // Remove the object from the scene so no more updates | ||
775 | // are sent. Doing this before the below changes will ensure | ||
776 | // updates can't cause "HUD artefacts" | ||
777 | m_scene.DeleteSceneObject(so, false, false); | ||
759 | 778 | ||
760 | // Prepare sog for storage | 779 | // Prepare sog for storage |
761 | so.AttachedAvatar = UUID.Zero; | 780 | so.AttachedAvatar = UUID.Zero; |
762 | so.RootPart.SetParentLocalId(0); | 781 | so.RootPart.SetParentLocalId(0); |
763 | so.IsAttachment = false; | 782 | so.IsAttachment = false; |
764 | 783 | ||
765 | // We cannot use AbsolutePosition here because that would | 784 | if (saveChanged) |
766 | // attempt to cross the prim as it is detached | 785 | { |
767 | so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); | 786 | // We cannot use AbsolutePosition here because that would |
787 | // attempt to cross the prim as it is detached | ||
788 | so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); | ||
789 | |||
790 | UpdateKnownItem(sp, so, scriptedState); | ||
791 | } | ||
792 | |||
793 | // Now, remove the scripts | ||
794 | so.RemoveScriptInstances(true); | ||
795 | } | ||
768 | 796 | ||
769 | UpdateKnownItem(sp, so, true); | 797 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) |
798 | { | ||
799 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
800 | |||
801 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | ||
802 | sp.RemoveAttachment(so); | ||
770 | 803 | ||
771 | // This MUST happen AFTER serialization because it will | 804 | UpdateDetachedObject(sp, so); |
772 | // either stop or remove the scripts. Both will cause scripts | ||
773 | // to be serialized in a stopped state with the true run | ||
774 | // state already lost. | ||
775 | m_scene.DeleteSceneObject(so, false, true); | ||
776 | } | 805 | } |
777 | 806 | ||
778 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 807 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 410eda0..11a13e1 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs | |||
@@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
66 | /// <param name="sp">The presence closing</param> | 66 | /// <param name="sp">The presence closing</param> |
67 | /// <param name="saveChanged">Save changed attachments.</param> | 67 | /// <param name="saveChanged">Save changed attachments.</param> |
68 | /// <param name="saveAllScripted">Save attachments with scripts even if they haven't changed.</para> | 68 | /// <param name="saveAllScripted">Save attachments with scripts even if they haven't changed.</para> |
69 | void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted); | 69 | void DeRezAttachments(IScenePresence sp); |
70 | 70 | ||
71 | /// <summary> | 71 | /// <summary> |
72 | /// Delete all the presence's attachments from the scene | 72 | /// Delete all the presence's attachments from the scene |
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index e6b926c..3f68ee0 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs | |||
@@ -40,6 +40,8 @@ namespace OpenSim.Region.Framework.Interfaces | |||
40 | /// </remarks> | 40 | /// </remarks> |
41 | public interface IScenePresence : ISceneAgent | 41 | public interface IScenePresence : ISceneAgent |
42 | { | 42 | { |
43 | PresenceType PresenceType { get; } | ||
44 | |||
43 | /// <summary> | 45 | /// <summary> |
44 | /// Copy of the script states while the agent is in transit. This state may | 46 | /// Copy of the script states while the agent is in transit. This state may |
45 | /// need to be placed back in case of transfer fail. | 47 | /// need to be placed back in case of transfer fail. |
@@ -83,4 +85,4 @@ namespace OpenSim.Region.Framework.Interfaces | |||
83 | void RemoveAttachment(SceneObjectGroup gobj); | 85 | void RemoveAttachment(SceneObjectGroup gobj); |
84 | void ClearAttachments(); | 86 | void ClearAttachments(); |
85 | } | 87 | } |
86 | } \ No newline at end of file | 88 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f501828..ad9e91d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -3461,17 +3461,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3461 | { | 3461 | { |
3462 | if (AttachmentsModule != null) | 3462 | if (AttachmentsModule != null) |
3463 | { | 3463 | { |
3464 | // Don't save attachments for HG visitors, it | 3464 | AttachmentsModule.DeRezAttachments(avatar); |
3465 | // messes up their inventory. When a HG visitor logs | ||
3466 | // out on a foreign grid, their attachments will be | ||
3467 | // reloaded in the state they were in when they left | ||
3468 | // the home grid. This is best anyway as the visited | ||
3469 | // grid may use an incompatible script engine. | ||
3470 | bool saveChanged | ||
3471 | = avatar.PresenceType != PresenceType.Npc | ||
3472 | && (UserManagementModule == null || UserManagementModule.IsLocalGridUser(avatar.UUID)); | ||
3473 | |||
3474 | AttachmentsModule.DeRezAttachments(avatar, saveChanged, false); | ||
3475 | } | 3465 | } |
3476 | 3466 | ||
3477 | ForEachClient( | 3467 | ForEachClient( |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 2372d6b..0d292e7 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -151,6 +151,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
151 | ToOriginalXmlFormat(sceneObject, writer, doScriptStates, false); | 151 | ToOriginalXmlFormat(sceneObject, writer, doScriptStates, false); |
152 | } | 152 | } |
153 | 153 | ||
154 | public static string ToOriginalXmlFormat(SceneObjectGroup sceneObject, string scriptedState) | ||
155 | { | ||
156 | using (StringWriter sw = new StringWriter()) | ||
157 | { | ||
158 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | ||
159 | { | ||
160 | writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); | ||
161 | |||
162 | ToOriginalXmlFormat(sceneObject, writer, false, true); | ||
163 | |||
164 | writer.WriteRaw(scriptedState); | ||
165 | |||
166 | writer.WriteEndElement(); | ||
167 | } | ||
168 | return sw.ToString(); | ||
169 | } | ||
170 | } | ||
171 | |||
154 | /// <summary> | 172 | /// <summary> |
155 | /// Serialize a scene object to the original xml format | 173 | /// Serialize a scene object to the original xml format |
156 | /// </summary> | 174 | /// </summary> |