diff options
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 306 |
1 files changed, 167 insertions, 139 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index ed4506c..ab7e932 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -241,12 +241,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
241 | 241 | ||
242 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); | 242 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); |
243 | 243 | ||
244 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | ||
245 | |||
246 | if (attachments.Count <= 0) | ||
247 | return; | ||
248 | |||
249 | Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); | ||
250 | |||
251 | foreach (SceneObjectGroup so in attachments) | ||
252 | { | ||
253 | // Scripts MUST be snapshotted before the object is | ||
254 | // removed from the scene because doing otherwise will | ||
255 | // clobber the run flag | ||
256 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from | ||
257 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | ||
258 | scriptStates[so] = PrepareScriptInstanceForSave(so, false); | ||
259 | } | ||
260 | |||
244 | lock (sp.AttachmentsSyncLock) | 261 | lock (sp.AttachmentsSyncLock) |
245 | { | 262 | { |
246 | foreach (SceneObjectGroup so in sp.GetAttachments()) | 263 | foreach (SceneObjectGroup so in attachments) |
247 | { | 264 | UpdateDetachedObject(sp, so, scriptStates[so]); |
248 | UpdateDetachedObject(sp, so); | ||
249 | } | ||
250 | 265 | ||
251 | sp.ClearAttachments(); | 266 | sp.ClearAttachments(); |
252 | } | 267 | } |
@@ -285,32 +300,50 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
285 | 300 | ||
286 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool append) | 301 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp, bool append) |
287 | { | 302 | { |
288 | lock (sp.AttachmentsSyncLock) | ||
289 | { | ||
290 | // m_log.DebugFormat( | 303 | // m_log.DebugFormat( |
291 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | 304 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", |
292 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | 305 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); |
293 | 306 | ||
294 | if (group.GetSittingAvatarsCount() != 0) | 307 | if (group.GetSittingAvatarsCount() != 0) |
295 | { | 308 | { |
296 | // m_log.WarnFormat( | 309 | // m_log.WarnFormat( |
297 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", | 310 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", |
298 | // group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); | 311 | // group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); |
299 | 312 | ||
300 | return false; | 313 | return false; |
301 | } | 314 | } |
302 | 315 | ||
303 | if (sp.GetAttachments(attachmentPt).Contains(group)) | 316 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); |
317 | if (attachments.Contains(group)) | ||
318 | { | ||
319 | // m_log.WarnFormat( | ||
320 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
321 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | ||
322 | |||
323 | return false; | ||
324 | } | ||
325 | |||
326 | // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones | ||
327 | while (attachments.Count >= 5) | ||
328 | { | ||
329 | if (attachments[0].FromItemID != UUID.Zero) | ||
330 | DetachSingleAttachmentToInv(sp, attachments[0]); | ||
331 | attachments.RemoveAt(0); | ||
332 | } | ||
333 | |||
334 | // If we're not appending, remove the rest as well | ||
335 | if (attachments.Count != 0 && !append) | ||
336 | { | ||
337 | foreach (SceneObjectGroup g in attachments) | ||
304 | { | 338 | { |
305 | // m_log.WarnFormat( | 339 | if (g.FromItemID != UUID.Zero) |
306 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | 340 | DetachSingleAttachmentToInv(sp, g); |
307 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | ||
308 | |||
309 | return false; | ||
310 | } | 341 | } |
311 | 342 | } | |
343 | |||
344 | lock (sp.AttachmentsSyncLock) | ||
345 | { | ||
312 | Vector3 attachPos = group.AbsolutePosition; | 346 | Vector3 attachPos = group.AbsolutePosition; |
313 | |||
314 | // If the attachment point isn't the same as the one previously used | 347 | // If the attachment point isn't the same as the one previously used |
315 | // set it's offset position = 0 so that it appears on the attachment point | 348 | // set it's offset position = 0 so that it appears on the attachment point |
316 | // and not in a weird location somewhere unknown. | 349 | // and not in a weird location somewhere unknown. |
@@ -318,14 +351,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
318 | { | 351 | { |
319 | attachPos = Vector3.Zero; | 352 | attachPos = Vector3.Zero; |
320 | } | 353 | } |
321 | 354 | ||
322 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | 355 | // AttachmentPt 0 means the client chose to 'wear' the attachment. |
323 | if (attachmentPt == 0) | 356 | if (attachmentPt == 0) |
324 | { | 357 | { |
325 | // Check object for stored attachment point | 358 | // Check object for stored attachment point |
326 | attachmentPt = group.AttachmentPoint; | 359 | attachmentPt = group.AttachmentPoint; |
327 | } | 360 | } |
328 | 361 | ||
329 | // if we still didn't find a suitable attachment point....... | 362 | // if we still didn't find a suitable attachment point....... |
330 | if (attachmentPt == 0) | 363 | if (attachmentPt == 0) |
331 | { | 364 | { |
@@ -333,7 +366,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
333 | attachmentPt = (uint)AttachmentPoint.LeftHand; | 366 | attachmentPt = (uint)AttachmentPoint.LeftHand; |
334 | attachPos = Vector3.Zero; | 367 | attachPos = Vector3.Zero; |
335 | } | 368 | } |
336 | 369 | ||
337 | group.AttachmentPoint = attachmentPt; | 370 | group.AttachmentPoint = attachmentPt; |
338 | group.AbsolutePosition = attachPos; | 371 | group.AbsolutePosition = attachPos; |
339 | 372 | ||
@@ -350,24 +383,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
350 | { | 383 | { |
351 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | 384 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); |
352 | 385 | ||
353 | // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones | ||
354 | while (attachments.Count >= 5) | ||
355 | { | ||
356 | if (attachments[0].FromItemID != UUID.Zero) | ||
357 | DetachSingleAttachmentToInvInternal(sp, attachments[0]); | ||
358 | attachments.RemoveAt(0); | ||
359 | } | ||
360 | |||
361 | // If we're not appending, remove the rest as well | ||
362 | if (attachments.Count != 0 && !append) | ||
363 | { | ||
364 | foreach (SceneObjectGroup g in attachments) | ||
365 | { | ||
366 | if (g.FromItemID != UUID.Zero) | ||
367 | DetachSingleAttachmentToInvInternal(sp, g); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | // Add the new attachment to inventory if we don't already have it. | 386 | // Add the new attachment to inventory if we don't already have it. |
372 | if (!temp) | 387 | if (!temp) |
373 | { | 388 | { |
@@ -426,12 +441,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
426 | return; | 441 | return; |
427 | 442 | ||
428 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); | 443 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); |
429 | lock (sp.AttachmentsSyncLock) | 444 | |
445 | foreach (KeyValuePair<UUID, uint> rez in rezlist) | ||
430 | { | 446 | { |
431 | foreach (KeyValuePair<UUID, uint> rez in rezlist) | 447 | RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value); |
432 | { | ||
433 | RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value); | ||
434 | } | ||
435 | } | 448 | } |
436 | } | 449 | } |
437 | 450 | ||
@@ -511,25 +524,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
511 | 524 | ||
512 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) | 525 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) |
513 | { | 526 | { |
527 | if (so.AttachedAvatar != sp.UUID) | ||
528 | { | ||
529 | m_log.WarnFormat( | ||
530 | "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}", | ||
531 | so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName); | ||
532 | |||
533 | return; | ||
534 | } | ||
535 | |||
536 | // Scripts MUST be snapshotted before the object is | ||
537 | // removed from the scene because doing otherwise will | ||
538 | // clobber the run flag | ||
539 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from | ||
540 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | ||
541 | string scriptedState = PrepareScriptInstanceForSave(so, true); | ||
542 | |||
514 | lock (sp.AttachmentsSyncLock) | 543 | lock (sp.AttachmentsSyncLock) |
515 | { | 544 | { |
516 | // Save avatar attachment information | 545 | // Save avatar attachment information |
517 | // m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); | 546 | // m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); |
518 | 547 | ||
519 | if (so.AttachedAvatar != sp.UUID) | ||
520 | { | ||
521 | m_log.WarnFormat( | ||
522 | "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}", | ||
523 | so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName); | ||
524 | |||
525 | return; | ||
526 | } | ||
527 | |||
528 | bool changed = sp.Appearance.DetachAttachment(so.FromItemID); | 548 | bool changed = sp.Appearance.DetachAttachment(so.FromItemID); |
529 | if (changed && m_scene.AvatarFactory != null) | 549 | if (changed && m_scene.AvatarFactory != null) |
530 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 550 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
531 | 551 | ||
532 | DetachSingleAttachmentToInvInternal(sp, so); | 552 | sp.RemoveAttachment(so); |
553 | UpdateDetachedObject(sp, so, scriptedState); | ||
533 | } | 554 | } |
534 | } | 555 | } |
535 | 556 | ||
@@ -739,8 +760,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
739 | return newItem; | 760 | return newItem; |
740 | } | 761 | } |
741 | 762 | ||
742 | private string GetObjectScriptStates(SceneObjectGroup grp) | 763 | /// <summary> |
764 | /// Prepares the script instance for save. | ||
765 | /// </summary> | ||
766 | /// <remarks> | ||
767 | /// This involves triggering the detach event and getting the script state (which also stops the script) | ||
768 | /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a | ||
769 | /// running script is performing attachment operations. | ||
770 | /// </remarks> | ||
771 | /// <returns> | ||
772 | /// The script state ready for persistence. | ||
773 | /// </returns> | ||
774 | /// <param name='grp'> | ||
775 | /// </param> | ||
776 | /// <param name='fireDetachEvent'> | ||
777 | /// If true, then fire the script event before we save its state. | ||
778 | /// </param> | ||
779 | private string PrepareScriptInstanceForSave(SceneObjectGroup grp, bool fireDetachEvent) | ||
743 | { | 780 | { |
781 | if (fireDetachEvent) | ||
782 | m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); | ||
783 | |||
744 | using (StringWriter sw = new StringWriter()) | 784 | using (StringWriter sw = new StringWriter()) |
745 | { | 785 | { |
746 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | 786 | using (XmlTextWriter writer = new XmlTextWriter(sw)) |
@@ -752,7 +792,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
752 | } | 792 | } |
753 | } | 793 | } |
754 | 794 | ||
755 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) | 795 | private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so, string scriptedState) |
756 | { | 796 | { |
757 | // Don't save attachments for HG visitors, it | 797 | // Don't save attachments for HG visitors, it |
758 | // messes up their inventory. When a HG visitor logs | 798 | // messes up their inventory. When a HG visitor logs |
@@ -765,11 +805,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
765 | && (m_scene.UserManagementModule == null | 805 | && (m_scene.UserManagementModule == null |
766 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); | 806 | || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); |
767 | 807 | ||
768 | // Scripts MUST be snapshotted before the object is | ||
769 | // removed from the scene because doing otherwise will | ||
770 | // clobber the run flag | ||
771 | string scriptedState = GetObjectScriptStates(so); | ||
772 | |||
773 | // Remove the object from the scene so no more updates | 808 | // Remove the object from the scene so no more updates |
774 | // are sent. Doing this before the below changes will ensure | 809 | // are sent. Doing this before the below changes will ensure |
775 | // updates can't cause "HUD artefacts" | 810 | // updates can't cause "HUD artefacts" |
@@ -793,91 +828,87 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
793 | so.RemoveScriptInstances(true); | 828 | so.RemoveScriptInstances(true); |
794 | } | 829 | } |
795 | 830 | ||
796 | private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) | ||
797 | { | ||
798 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
799 | |||
800 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); | ||
801 | sp.RemoveAttachment(so); | ||
802 | |||
803 | UpdateDetachedObject(sp, so); | ||
804 | } | ||
805 | |||
806 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 831 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |
807 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) | 832 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) |
808 | { | 833 | { |
809 | if (m_invAccessModule == null) | 834 | if (m_invAccessModule == null) |
810 | return null; | 835 | return null; |
811 | 836 | ||
812 | lock (sp.AttachmentsSyncLock) | 837 | SceneObjectGroup objatt; |
838 | |||
839 | if (itemID != UUID.Zero) | ||
840 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
841 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
842 | false, false, sp.UUID, true); | ||
843 | else | ||
844 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
845 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
846 | false, false, sp.UUID, true); | ||
847 | |||
848 | if (objatt == null) | ||
813 | { | 849 | { |
814 | SceneObjectGroup objatt; | 850 | m_log.WarnFormat( |
851 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
852 | itemID, sp.Name, attachmentPt); | ||
815 | 853 | ||
816 | if (itemID != UUID.Zero) | 854 | return null; |
817 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | 855 | } |
818 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
819 | false, false, sp.UUID, true); | ||
820 | else | ||
821 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | ||
822 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
823 | false, false, sp.UUID, true); | ||
824 | 856 | ||
825 | if (objatt != null) | 857 | // Remove any previous attachments |
826 | { | 858 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); |
859 | string previousAttachmentScriptedState = null; | ||
860 | |||
861 | // At the moment we can only deal with a single attachment | ||
862 | if (attachments.Count != 0) | ||
863 | DetachSingleAttachmentToInv(sp, attachments[0]); | ||
864 | |||
865 | lock (sp.AttachmentsSyncLock) | ||
866 | { | ||
827 | // m_log.DebugFormat( | 867 | // m_log.DebugFormat( |
828 | // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 868 | // "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", |
829 | // objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 869 | // objatt.Name, sp.Name, attachmentPt, m_scene.Name); |
830 | 870 | ||
831 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 871 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
832 | objatt.HasGroupChanged = false; | 872 | objatt.HasGroupChanged = false; |
833 | bool tainted = false; | 873 | bool tainted = false; |
834 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | 874 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) |
835 | tainted = true; | 875 | tainted = true; |
836 | 876 | ||
837 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal | 877 | // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal |
838 | // course of events. If not, then it's probably not worth trying to recover the situation | 878 | // course of events. If not, then it's probably not worth trying to recover the situation |
839 | // since this is more likely to trigger further exceptions and confuse later debugging. If | 879 | // since this is more likely to trigger further exceptions and confuse later debugging. If |
840 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent | 880 | // exceptions can be thrown in expected error conditions (not NREs) then make this consistent |
841 | // since other normal error conditions will simply return false instead. | 881 | // since other normal error conditions will simply return false instead. |
842 | // This will throw if the attachment fails | 882 | // This will throw if the attachment fails |
843 | try | 883 | try |
844 | { | 884 | { |
845 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, append); | 885 | AttachObjectInternal(sp, objatt, attachmentPt, false, false, append); |
846 | } | 886 | } |
847 | catch (Exception e) | 887 | catch (Exception e) |
848 | { | 888 | { |
849 | m_log.ErrorFormat( | 889 | m_log.ErrorFormat( |
850 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | 890 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", |
851 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | 891 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); |
852 | |||
853 | // Make sure the object doesn't stick around and bail | ||
854 | sp.RemoveAttachment(objatt); | ||
855 | m_scene.DeleteSceneObject(objatt, false); | ||
856 | return null; | ||
857 | } | ||
858 | 892 | ||
859 | if (tainted) | 893 | // Make sure the object doesn't stick around and bail |
860 | objatt.HasGroupChanged = true; | 894 | sp.RemoveAttachment(objatt); |
895 | m_scene.DeleteSceneObject(objatt, false); | ||
896 | return null; | ||
897 | } | ||
861 | 898 | ||
862 | // Fire after attach, so we don't get messy perms dialogs | 899 | if (tainted) |
863 | // 4 == AttachedRez | 900 | objatt.HasGroupChanged = true; |
864 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
865 | objatt.ResumeScripts(); | ||
866 | 901 | ||
867 | // Do this last so that event listeners have access to all the effects of the attachment | 902 | // Fire after attach, so we don't get messy perms dialogs |
868 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | 903 | // 4 == AttachedRez |
904 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
905 | objatt.ResumeScripts(); | ||
869 | 906 | ||
870 | return objatt; | 907 | // Do this last so that event listeners have access to all the effects of the attachment |
871 | } | 908 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); |
872 | else | ||
873 | { | ||
874 | m_log.WarnFormat( | ||
875 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
876 | itemID, sp.Name, attachmentPt); | ||
877 | } | ||
878 | } | ||
879 | 909 | ||
880 | return null; | 910 | return objatt; |
911 | } | ||
881 | } | 912 | } |
882 | 913 | ||
883 | /// <summary> | 914 | /// <summary> |
@@ -1035,17 +1066,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1035 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 1066 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
1036 | if (sp != null) | 1067 | if (sp != null) |
1037 | { | 1068 | { |
1038 | lock (sp.AttachmentsSyncLock) | 1069 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
1070 | |||
1071 | foreach (SceneObjectGroup group in attachments) | ||
1039 | { | 1072 | { |
1040 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | 1073 | if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) |
1041 | |||
1042 | foreach (SceneObjectGroup group in attachments) | ||
1043 | { | 1074 | { |
1044 | if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) | 1075 | DetachSingleAttachmentToInv(sp, group); |
1045 | { | 1076 | return; |
1046 | DetachSingleAttachmentToInv(sp, group); | ||
1047 | return; | ||
1048 | } | ||
1049 | } | 1077 | } |
1050 | } | 1078 | } |
1051 | } | 1079 | } |