diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 88 |
1 files changed, 59 insertions, 29 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 0f3b1e8..464dfd3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -28,6 +28,8 @@ | |||
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; | ||
32 | using System.Xml; | ||
31 | using log4net; | 33 | using log4net; |
32 | using Mono.Addins; | 34 | using Mono.Addins; |
33 | using Nini.Config; | 35 | using Nini.Config; |
@@ -202,7 +204,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
202 | } | 204 | } |
203 | } | 205 | } |
204 | 206 | ||
205 | public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted) | 207 | public void DeRezAttachments(IScenePresence sp) |
206 | { | 208 | { |
207 | if (!Enabled) | 209 | if (!Enabled) |
208 | return; | 210 | return; |
@@ -213,18 +215,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
213 | { | 215 | { |
214 | foreach (SceneObjectGroup so in sp.GetAttachments()) | 216 | foreach (SceneObjectGroup so in sp.GetAttachments()) |
215 | { | 217 | { |
216 | // We can only remove the script instances from the script engine after we've retrieved their xml state | 218 | UpdateDetachedObject(sp, so); |
217 | // when we update the attachment item. | ||
218 | m_scene.DeleteSceneObject(so, false, false); | ||
219 | |||
220 | if (saveChanged || saveAllScripted) | ||
221 | { | ||
222 | so.IsAttachment = false; | ||
223 | so.AbsolutePosition = so.RootPart.AttachedPos; | ||
224 | UpdateKnownItem(sp, so, saveAllScripted); | ||
225 | } | ||
226 | |||
227 | so.RemoveScriptInstances(true); | ||
228 | } | 219 | } |
229 | 220 | ||
230 | sp.ClearAttachments(); | 221 | sp.ClearAttachments(); |
@@ -528,7 +519,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
528 | /// <param name="sp"></param> | 519 | /// <param name="sp"></param> |
529 | /// <param name="grp"></param> | 520 | /// <param name="grp"></param> |
530 | /// <param name="saveAllScripted"></param> | 521 | /// <param name="saveAllScripted"></param> |
531 | private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) | 522 | private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) |
532 | { | 523 | { |
533 | // Saving attachments for NPCs messes them up for the real owner! | 524 | // Saving attachments for NPCs messes them up for the real owner! |
534 | INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); | 525 | INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); |
@@ -538,13 +529,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
538 | return; | 529 | return; |
539 | } | 530 | } |
540 | 531 | ||
541 | if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) | 532 | if (grp.HasGroupChanged) |
542 | { | 533 | { |
543 | // m_log.DebugFormat( | 534 | // m_log.DebugFormat( |
544 | // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", | 535 | // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", |
545 | // grp.UUID, grp.AttachmentPoint); | 536 | // grp.UUID, grp.AttachmentPoint); |
546 | 537 | ||
547 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); | 538 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); |
548 | 539 | ||
549 | InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); | 540 | InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); |
550 | item = m_scene.InventoryService.GetItem(item); | 541 | item = m_scene.InventoryService.GetItem(item); |
@@ -683,29 +674,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
683 | return newItem; | 674 | return newItem; |
684 | } | 675 | } |
685 | 676 | ||
686 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) | 677 | private string GetObjectScriptStates(SceneObjectGroup grp) |
687 | { | 678 | { |
688 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | 679 | using (StringWriter sw = new StringWriter()) |
680 | { | ||
681 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | ||
682 | { | ||
683 | grp.SaveScriptedState(writer); | ||
684 | } | ||
689 | 685 | ||
690 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | 686 | return sw.ToString(); |
691 | sp.RemoveAttachment(so); | 687 | } |
688 | } | ||
689 | |||
690 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) | ||
691 | { | ||
692 | // Don't save attachments for HG visitors, it | ||
693 | // messes up their inventory. When a HG visitor logs | ||
694 | // out on a foreign grid, their attachments will be | ||
695 | // reloaded in the state they were in when they left | ||
696 | // the home grid. This is best anyway as the visited | ||
697 | // grid may use an incompatible script engine. | ||
698 | bool saveChanged | ||
699 | = sp.PresenceType != PresenceType.Npc | ||
700 | && (m_scene.UserManagementModule == null | ||
701 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); | ||
702 | |||
703 | // Scripts MUST be snapshotted before the object is | ||
704 | // removed from the scene because doing otherwise will | ||
705 | // clobber the run flag | ||
706 | string scriptedState = GetObjectScriptStates(so); | ||
707 | |||
708 | // Remove the object from the scene so no more updates | ||
709 | // are sent. Doing this before the below changes will ensure | ||
710 | // updates can't cause "HUD artefacts" | ||
711 | m_scene.DeleteSceneObject(so, false, false); | ||
692 | 712 | ||
693 | // Prepare sog for storage | 713 | // Prepare sog for storage |
694 | so.AttachedAvatar = UUID.Zero; | 714 | so.AttachedAvatar = UUID.Zero; |
695 | so.RootPart.SetParentLocalId(0); | 715 | so.RootPart.SetParentLocalId(0); |
696 | so.IsAttachment = false; | 716 | so.IsAttachment = false; |
697 | 717 | ||
698 | // We cannot use AbsolutePosition here because that would | 718 | if (saveChanged) |
699 | // attempt to cross the prim as it is detached | 719 | { |
700 | so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); | 720 | // We cannot use AbsolutePosition here because that would |
721 | // attempt to cross the prim as it is detached | ||
722 | so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); | ||
723 | |||
724 | UpdateKnownItem(sp, so, scriptedState); | ||
725 | } | ||
726 | |||
727 | // Now, remove the scripts | ||
728 | so.RemoveScriptInstances(true); | ||
729 | } | ||
701 | 730 | ||
702 | UpdateKnownItem(sp, so, true); | 731 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) |
732 | { | ||
733 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
734 | |||
735 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | ||
736 | sp.RemoveAttachment(so); | ||
703 | 737 | ||
704 | // This MUST happen AFTER serialization because it will | 738 | UpdateDetachedObject(sp, so); |
705 | // either stop or remove the scripts. Both will cause scripts | ||
706 | // to be serialized in a stopped state with the true run | ||
707 | // state already lost. | ||
708 | m_scene.DeleteSceneObject(so, false, true); | ||
709 | } | 739 | } |
710 | 740 | ||
711 | private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 741 | private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |