aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs795
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs37
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs2
4 files changed, 409 insertions, 427 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 6eba249..09781c7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
46 public class AttachmentsModule : IAttachmentsModule, INonSharedRegionModule 46 public class AttachmentsModule : IAttachmentsModule, INonSharedRegionModule
47 { 47 {
48 #region INonSharedRegionModule
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 50
50 private Scene m_scene; 51 private Scene m_scene;
@@ -93,26 +94,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
93 { 94 {
94 RemoveRegion(m_scene); 95 RemoveRegion(m_scene);
95 } 96 }
96 97
97 public void SubscribeToClientEvents(IClientAPI client) 98 #endregion
98 { 99
99 client.OnRezSingleAttachmentFromInv += RezSingleAttachmentFromInventory; 100 #region IAttachmentsModule
100 client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachmentsFromInventory;
101 client.OnObjectAttach += AttachObject;
102 client.OnObjectDetach += DetachObject;
103 client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv;
104 client.OnObjectDrop += DetachSingleAttachmentToGround;
105 }
106
107 public void UnsubscribeFromClientEvents(IClientAPI client)
108 {
109 client.OnRezSingleAttachmentFromInv -= RezSingleAttachmentFromInventory;
110 client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachmentsFromInventory;
111 client.OnObjectAttach -= AttachObject;
112 client.OnObjectDetach -= DetachObject;
113 client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv;
114 client.OnObjectDrop -= DetachSingleAttachmentToGround;
115 }
116 101
117 /// <summary> 102 /// <summary>
118 /// RezAttachments. This should only be called upon login on the first region. 103 /// RezAttachments. This should only be called upon login on the first region.
@@ -175,7 +160,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
175// { 160// {
176 grp.IsAttachment = false; 161 grp.IsAttachment = false;
177 grp.AbsolutePosition = grp.RootPart.AttachedPos; 162 grp.AbsolutePosition = grp.RootPart.AttachedPos;
178 UpdateKnownItem(sp.ControllingClient, grp); 163 UpdateKnownItem(sp, grp);
179 grp.IsAttachment = true; 164 grp.IsAttachment = true;
180// } 165// }
181 } 166 }
@@ -198,75 +183,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
198 sp.ClearAttachments(); 183 sp.ClearAttachments();
199 } 184 }
200 185
201 /// <summary>
202 /// Called by client
203 /// </summary>
204 /// <param name="remoteClient"></param>
205 /// <param name="objectLocalID"></param>
206 /// <param name="AttachmentPt"></param>
207 /// <param name="silent"></param>
208 private void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
209 {
210// m_log.DebugFormat(
211// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
212// objectLocalID, remoteClient.Name, AttachmentPt, silent);
213
214 if (!Enabled)
215 return;
216
217 try
218 {
219 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
220
221 if (sp == null)
222 {
223 m_log.ErrorFormat(
224 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
225 return;
226 }
227
228 // If we can't take it, we can't attach it!
229 SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID);
230 if (part == null)
231 return;
232
233 if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId))
234 {
235 remoteClient.SendAgentAlertMessage(
236 "You don't have sufficient permissions to attach this object", false);
237
238 return;
239 }
240
241 if (part.OwnerID != remoteClient.AgentId) // Not ours
242 {
243 remoteClient.SendAgentAlertMessage(
244 "You don't have sufficient permissions to attach this object", false);
245 return;
246 }
247
248 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
249 // be removed when that functionality is implemented in opensim
250 AttachmentPt &= 0x7f;
251
252 // Calls attach with a Zero position
253 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))
254 {
255 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
256
257 // Save avatar attachment information
258 m_log.Debug(
259 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
260 + ", AttachmentPoint: " + AttachmentPt);
261
262 }
263 }
264 catch (Exception e)
265 {
266 m_log.ErrorFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}{1}", e.Message, e.StackTrace);
267 }
268 }
269
270 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) 186 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
271 { 187 {
272 lock (sp.AttachmentsSyncLock) 188 lock (sp.AttachmentsSyncLock)
@@ -328,7 +244,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
328 UUID oldAttachmentItemID = attachments[0].GetFromItemID(); 244 UUID oldAttachmentItemID = attachments[0].GetFromItemID();
329 245
330 if (oldAttachmentItemID != UUID.Zero) 246 if (oldAttachmentItemID != UUID.Zero)
331 DetachSingleAttachmentToInv(oldAttachmentItemID, sp); 247 DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
332 else 248 else
333 m_log.WarnFormat( 249 m_log.WarnFormat(
334 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", 250 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
@@ -338,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
338 // Add the new attachment to inventory if we don't already have it. 254 // Add the new attachment to inventory if we don't already have it.
339 UUID newAttachmentItemID = group.GetFromItemID(); 255 UUID newAttachmentItemID = group.GetFromItemID();
340 if (newAttachmentItemID == UUID.Zero) 256 if (newAttachmentItemID == UUID.Zero)
341 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; 257 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
342 258
343 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 259 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
344 } 260 }
@@ -347,63 +263,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
347 } 263 }
348 264
349 return true; 265 return true;
350 }
351
352 private void RezMultipleAttachmentsFromInventory(IClientAPI remoteClient, List<KeyValuePair<UUID, uint>> rezlist)
353 {
354 if (!Enabled)
355 return;
356
357 ScenePresence sp;
358 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out sp))
359 RezMultipleAttachmentsFromInventory(sp, rezlist);
360 else
361 m_log.ErrorFormat(
362 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
363 remoteClient.Name, remoteClient.AgentId);
364 return;
365 }
366
367 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
368 {
369 if (!Enabled)
370 return;
371
372// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
373 lock (sp.AttachmentsSyncLock)
374 {
375 foreach (KeyValuePair<UUID, uint> rez in rezlist)
376 {
377 RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value);
378 }
379 }
380 }
381
382 private ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
383 {
384 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
385 }
386
387 public ISceneEntity RezSingleAttachmentFromInventory(
388 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
389 {
390 if (!Enabled)
391 return null;
392
393 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
394
395 if (sp == null)
396 {
397 m_log.ErrorFormat(
398 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
399 remoteClient.Name, remoteClient.AgentId);
400 return null;
401 }
402
403 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
404 } 266 }
405 267
406 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 268 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
269 {
270 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null);
271 }
272
273 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
407 { 274 {
408 if (!Enabled) 275 if (!Enabled)
409 return null; 276 return null;
@@ -442,187 +309,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
442 return null; 309 return null;
443 } 310 }
444 311
445 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, null); 312 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
446 313
447 if (att == null) 314 if (att == null)
448 DetachSingleAttachmentToInv(itemID, sp.ControllingClient); 315 DetachSingleAttachmentToInv(sp, itemID);
449 316
450 return att; 317 return att;
451 } 318 }
452 319
453 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 320 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
454 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
455 {
456 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
457 if (invAccess != null)
458 {
459 lock (sp.AttachmentsSyncLock)
460 {
461 SceneObjectGroup objatt;
462
463 if (itemID != UUID.Zero)
464 objatt = invAccess.RezObject(sp.ControllingClient,
465 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
466 false, false, sp.UUID, true);
467 else
468 objatt = invAccess.RezObject(sp.ControllingClient,
469 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
470 false, false, sp.UUID, true);
471
472 // m_log.DebugFormat(
473 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
474 // objatt.Name, remoteClient.Name, AttachmentPt);
475
476 if (objatt != null)
477 {
478 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
479 objatt.HasGroupChanged = false;
480 bool tainted = false;
481 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
482 tainted = true;
483
484 // This will throw if the attachment fails
485 try
486 {
487 AttachObject(sp, objatt, attachmentPt, false);
488 }
489 catch (Exception e)
490 {
491 m_log.ErrorFormat(
492 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
493 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
494
495 // Make sure the object doesn't stick around and bail
496 sp.RemoveAttachment(objatt);
497 m_scene.DeleteSceneObject(objatt, false);
498 return null;
499 }
500
501 if (tainted)
502 objatt.HasGroupChanged = true;
503
504 // Fire after attach, so we don't get messy perms dialogs
505 // 4 == AttachedRez
506 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
507 objatt.ResumeScripts();
508
509 // Do this last so that event listeners have access to all the effects of the attachment
510 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
511
512 return objatt;
513 }
514 else
515 {
516 m_log.WarnFormat(
517 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
518 itemID, sp.Name, attachmentPt);
519 }
520
521 if (doc != null)
522 {
523 objatt.LoadScriptState(doc);
524 objatt.ResetOwnerChangeFlag();
525 }
526
527 // Fire after attach, so we don't get messy perms dialogs
528 // 4 == AttachedRez
529 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
530 objatt.ResumeScripts();
531
532 // Do this last so that event listeners have access to all the effects of the attachment
533 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
534 }
535 }
536
537 return null;
538 }
539
540 /// <summary>
541 /// Update the user inventory to reflect an attachment
542 /// </summary>
543 /// <param name="sp"></param>
544 /// <param name="AttachmentPt"></param>
545 /// <param name="itemID"></param>
546 /// <param name="att"></param>
547 private void ShowAttachInUserInventory(
548 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
549 {
550// m_log.DebugFormat(
551// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
552// att.Name, sp.Name, AttachmentPt, itemID);
553
554 if (UUID.Zero == itemID)
555 {
556 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID.");
557 return;
558 }
559
560 if (0 == AttachmentPt)
561 {
562 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error attachment point.");
563 return;
564 }
565
566 if (null == att.RootPart)
567 {
568 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment for a prim without the rootpart!");
569 return;
570 }
571 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
572
573
574
575
576
577
578 item = m_scene.InventoryService.GetItem(item);
579 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
580 if (changed && m_scene.AvatarFactory != null)
581 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
582 }
583
584 public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
585 {
586// m_log.DebugFormat(
587// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
588
589 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
590 if (group != null)
591 {
592 DetachSingleAttachmentToInv(group.GetFromItemID(), remoteClient);
593 }
594 }
595
596 public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient)
597 { 321 {
598 if (!Enabled) 322 if (!Enabled)
599 return; 323 return;
600 324
601 ScenePresence presence; 325 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
602 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 326 lock (sp.AttachmentsSyncLock)
603 { 327 {
604 lock (presence.AttachmentsSyncLock) 328 foreach (KeyValuePair<UUID, uint> rez in rezlist)
605 { 329 {
606 // Save avatar attachment information 330 RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value);
607 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
608
609 bool changed = presence.Appearance.DetachAttachment(itemID);
610 if (changed && m_scene.AvatarFactory != null)
611 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
612
613 DetachSingleAttachmentToInv(itemID, presence);
614 } 331 }
615 } 332 }
616 }
617
618 private void DetachSingleAttachmentToGround(uint soLocalId, IClientAPI remoteClient)
619 {
620 if (!Enabled)
621 return;
622
623 ScenePresence sp;
624 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out sp))
625 DetachSingleAttachmentToGround(sp, soLocalId);
626 } 333 }
627 334
628 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 335 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
@@ -652,27 +359,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
652 { 359 {
653 if (!m_scene.Permissions.CanRezObject( 360 if (!m_scene.Permissions.CanRezObject(
654 so.PrimCount, sp.UUID, sp.AbsolutePosition)) 361 so.PrimCount, sp.UUID, sp.AbsolutePosition))
655 return; 362 return;
656 363
657 bool changed = sp.Appearance.DetachAttachment(inventoryID); 364 bool changed = sp.Appearance.DetachAttachment(inventoryID);
658 if (changed && m_scene.AvatarFactory != null) 365 if (changed && m_scene.AvatarFactory != null)
659 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 366 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
660 367
661 sp.RemoveAttachment(so); 368 sp.RemoveAttachment(so);
662 369
663 SceneObjectPart rootPart = so.RootPart; 370 SceneObjectPart rootPart = so.RootPart;
664 rootPart.FromItemID = UUID.Zero; 371 rootPart.FromItemID = UUID.Zero;
665 so.AbsolutePosition = sp.AbsolutePosition; 372 so.AbsolutePosition = sp.AbsolutePosition;
666 so.AttachedAvatar = UUID.Zero; 373 so.AttachedAvatar = UUID.Zero;
667 rootPart.SetParentLocalId(0); 374 rootPart.SetParentLocalId(0);
668 so.ClearPartAttachmentData(); 375 so.ClearPartAttachmentData();
669 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim); 376 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
670 so.HasGroupChanged = true; 377 so.HasGroupChanged = true;
671 rootPart.Rezzed = DateTime.Now; 378 rootPart.Rezzed = DateTime.Now;
672 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 379 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
673 so.AttachToBackup(); 380 so.AttachToBackup();
674 m_scene.EventManager.TriggerParcelPrimCountTainted(); 381 m_scene.EventManager.TriggerParcelPrimCountTainted();
675 rootPart.ScheduleFullUpdate(); 382 rootPart.ScheduleFullUpdate();
676 rootPart.ClearUndoState(); 383 rootPart.ClearUndoState();
677 384
678 List<UUID> uuids = new List<UUID>(); 385 List<UUID> uuids = new List<UUID>();
@@ -683,46 +390,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
683 390
684 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 391 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
685 } 392 }
686
687 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
688 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
689 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
690 {
691// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
692
693 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
694 return;
695
696 // We can NOT use the dictionries here, as we are looking
697 // for an entity by the fromAssetID, which is NOT the prim UUID
698 EntityBase[] detachEntities = m_scene.GetEntities();
699 SceneObjectGroup group;
700 393
394 public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID)
395 {
701 lock (sp.AttachmentsSyncLock) 396 lock (sp.AttachmentsSyncLock)
702 { 397 {
703 foreach (EntityBase entity in detachEntities) 398 // Save avatar attachment information
704 { 399 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
705 if (entity is SceneObjectGroup)
706 {
707 group = (SceneObjectGroup)entity; if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
708 // CM / XMREngine!!!! Needed to conclude attach event
709 //SceneObjectSerializer.ToOriginalXmlFormat(group);
710 group.DetachToInventoryPrep();
711 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
712 400
713 // Prepare sog for storage 401 bool changed = sp.Appearance.DetachAttachment(itemID);
714 group.AttachedAvatar = UUID.Zero; 402 if (changed && m_scene.AvatarFactory != null)
715 group.RootPart.SetParentLocalId(0); 403 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
716 group.IsAttachment = false;
717 group.AbsolutePosition = group.RootPart.AttachedPos;
718
719 UpdateKnownItem(sp.ControllingClient, group);
720 m_scene.DeleteSceneObject(group, false);
721 404
722 return; 405 DetachSingleAttachmentToInvInternal(sp, itemID);
723 }
724 }
725 }
726 } 406 }
727 } 407 }
728 408
@@ -744,7 +424,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
744 sog.AttachmentPoint = attachmentPoint; 424 sog.AttachmentPoint = attachmentPoint;
745 sog.HasGroupChanged = true; 425 sog.HasGroupChanged = true;
746 } 426 }
747 427
428 #endregion
429
430 #region AttachmentModule private methods
431
432 // This is public but is not part of the IAttachmentsModule interface.
433 // RegionCombiner module needs to poke at it to deliver client events.
434 // This breaks the encapsulation of the module and should get fixed somehow.
435 public void SubscribeToClientEvents(IClientAPI client)
436 {
437 client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv;
438 client.OnRezMultipleAttachmentsFromInv += Client_OnRezMultipleAttachmentsFromInv;
439 client.OnObjectAttach += Client_OnObjectAttach;
440 client.OnObjectDetach += Client_OnObjectDetach;
441 client.OnDetachAttachmentIntoInv += Client_OnDetachAttachmentIntoInv;
442 client.OnObjectDrop += Client_OnObjectDrop;
443 }
444
445 // This is public but is not part of the IAttachmentsModule interface.
446 // RegionCombiner module needs to poke at it to deliver client events.
447 // This breaks the encapsulation of the module and should get fixed somehow.
448 public void UnsubscribeFromClientEvents(IClientAPI client)
449 {
450 client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv;
451 client.OnRezMultipleAttachmentsFromInv -= Client_OnRezMultipleAttachmentsFromInv;
452 client.OnObjectAttach -= Client_OnObjectAttach;
453 client.OnObjectDetach -= Client_OnObjectDetach;
454 client.OnDetachAttachmentIntoInv -= Client_OnDetachAttachmentIntoInv;
455 client.OnObjectDrop -= Client_OnObjectDrop;
456 }
457
748 /// <summary> 458 /// <summary>
749 /// Update the attachment asset for the new sog details if they have changed. 459 /// Update the attachment asset for the new sog details if they have changed.
750 /// </summary> 460 /// </summary>
@@ -752,9 +462,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
752 /// This is essential for preserving attachment attributes such as permission. Unlike normal scene objects, 462 /// This is essential for preserving attachment attributes such as permission. Unlike normal scene objects,
753 /// these details are not stored on the region. 463 /// these details are not stored on the region.
754 /// </remarks> 464 /// </remarks>
755 /// <param name="remoteClient"></param> 465 /// <param name="sp"></param>
756 /// <param name="grp"></param> 466 /// <param name="grp"></param>
757 private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp) 467 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp)
758 { 468 {
759 if (grp.HasGroupChanged || grp.ContainsScripts()) 469 if (grp.HasGroupChanged || grp.ContainsScripts())
760 { 470 {
@@ -764,7 +474,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
764 474
765 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 475 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
766 476
767 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId); 477 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), sp.UUID);
768 item = m_scene.InventoryService.GetItem(item); 478 item = m_scene.InventoryService.GetItem(item);
769 479
770 if (item != null) 480 if (item != null)
@@ -774,7 +484,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
774 grp.GetPartDescription(grp.LocalId), 484 grp.GetPartDescription(grp.LocalId),
775 (sbyte)AssetType.Object, 485 (sbyte)AssetType.Object,
776 Utils.StringToBytes(sceneObjectXml), 486 Utils.StringToBytes(sceneObjectXml),
777 remoteClient.AgentId); 487 sp.UUID);
778 m_scene.AssetService.Store(asset); 488 m_scene.AssetService.Store(asset);
779 489
780 item.AssetID = asset.FullID; 490 item.AssetID = asset.FullID;
@@ -786,8 +496,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
786 m_scene.InventoryService.UpdateItem(item); 496 m_scene.InventoryService.UpdateItem(item);
787 497
788 // this gets called when the agent logs off! 498 // this gets called when the agent logs off!
789 if (remoteClient != null) 499 if (sp.ControllingClient != null)
790 remoteClient.SendInventoryItemCreateUpdate(item, 0); 500 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
791 } 501 }
792 } 502 }
793 else 503 else
@@ -796,8 +506,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
796 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", 506 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
797 grp.UUID, grp.AttachmentPoint); 507 grp.UUID, grp.AttachmentPoint);
798 } 508 }
799 } 509 }
800 510
801 /// <summary> 511 /// <summary>
802 /// Attach this scene object to the given avatar. 512 /// Attach this scene object to the given avatar.
803 /// </summary> 513 /// </summary>
@@ -811,19 +521,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
811 /// <param name="attachOffset"></param> 521 /// <param name="attachOffset"></param>
812 /// <param name="silent"></param> 522 /// <param name="silent"></param>
813 private void AttachToAgent( 523 private void AttachToAgent(
814 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 524 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
815 { 525 {
816// m_log.DebugFormat( 526 // m_log.DebugFormat(
817// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 527 // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
818// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 528 // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
819 529
820 so.DetachFromBackup(); 530 so.DetachFromBackup();
821 531
822 // Remove from database and parcel prim count 532 // Remove from database and parcel prim count
823 m_scene.DeleteFromStorage(so.UUID); 533 m_scene.DeleteFromStorage(so.UUID);
824 m_scene.EventManager.TriggerParcelPrimCountTainted(); 534 m_scene.EventManager.TriggerParcelPrimCountTainted();
825 535
826 so.AttachedAvatar = avatar.UUID; 536 so.AttachedAvatar = sp.UUID;
827 537
828 if (so.RootPart.PhysActor != null) 538 if (so.RootPart.PhysActor != null)
829 { 539 {
@@ -834,17 +544,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
834 so.AbsolutePosition = attachOffset; 544 so.AbsolutePosition = attachOffset;
835 so.RootPart.AttachedPos = attachOffset; 545 so.RootPart.AttachedPos = attachOffset;
836 so.IsAttachment = true; 546 so.IsAttachment = true;
837 so.RootPart.SetParentLocalId(avatar.LocalId); 547 so.RootPart.SetParentLocalId(sp.LocalId);
838 so.AttachmentPoint = attachmentpoint; 548 so.AttachmentPoint = attachmentpoint;
839 549
840 avatar.AddAttachment(so); 550 sp.AddAttachment(so);
841 551
842 if (!silent) 552 if (!silent)
843 { 553 {
844 so.IsSelected = false; // fudge.... 554 so.IsSelected = false; // fudge....
845 so.ScheduleGroupForFullUpdate(); 555 so.ScheduleGroupForFullUpdate();
846 } 556 }
847 557
848 // In case it is later dropped again, don't let 558 // In case it is later dropped again, don't let
849 // it get cleaned up 559 // it get cleaned up
850 so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); 560 so.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -856,19 +566,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
856 /// <param name="remoteClient"></param> 566 /// <param name="remoteClient"></param>
857 /// <param name="grp"></param> 567 /// <param name="grp"></param>
858 /// <returns>The user inventory item created that holds the attachment.</returns> 568 /// <returns>The user inventory item created that holds the attachment.</returns>
859 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) 569 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
860 { 570 {
861// m_log.DebugFormat( 571 // m_log.DebugFormat(
862// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 572 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
863// grp.Name, grp.LocalId, remoteClient.Name); 573 // grp.Name, grp.LocalId, remoteClient.Name);
864 uint regionSize = Constants.RegionSize; //Avoid VS error "The operation overflows at compile time in checked mode" 574
865 Vector3 inventoryStoredPosition = new Vector3 575 Vector3 inventoryStoredPosition = new Vector3
866 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 576 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
867 ? regionSize - 6 577 ? (float)Constants.RegionSize - 6
868 : grp.AbsolutePosition.X) 578 : grp.AbsolutePosition.X)
869 , 579 ,
870 (grp.AbsolutePosition.Y > (int)Constants.RegionSize) 580 (grp.AbsolutePosition.Y > (int)Constants.RegionSize)
871 ? regionSize - 6 581 ? (float)Constants.RegionSize - 6
872 : grp.AbsolutePosition.Y, 582 : grp.AbsolutePosition.Y,
873 grp.AbsolutePosition.Z); 583 grp.AbsolutePosition.Z);
874 584
@@ -889,14 +599,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
889 grp.GetPartDescription(grp.LocalId), 599 grp.GetPartDescription(grp.LocalId),
890 (sbyte)AssetType.Object, 600 (sbyte)AssetType.Object,
891 Utils.StringToBytes(sceneObjectXml), 601 Utils.StringToBytes(sceneObjectXml),
892 remoteClient.AgentId); 602 sp.UUID);
893 603
894 m_scene.AssetService.Store(asset); 604 m_scene.AssetService.Store(asset);
895 605
896 InventoryItemBase item = new InventoryItemBase(); 606 InventoryItemBase item = new InventoryItemBase();
897 item.CreatorId = grp.RootPart.CreatorID.ToString(); 607 item.CreatorId = grp.RootPart.CreatorID.ToString();
898 item.CreatorData = grp.RootPart.CreatorData; 608 item.CreatorData = grp.RootPart.CreatorData;
899 item.Owner = remoteClient.AgentId; 609 item.Owner = sp.UUID;
900 item.ID = UUID.Random(); 610 item.ID = UUID.Random();
901 item.AssetID = asset.FullID; 611 item.AssetID = asset.FullID;
902 item.Description = asset.Description; 612 item.Description = asset.Description;
@@ -904,13 +614,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
904 item.AssetType = asset.Type; 614 item.AssetType = asset.Type;
905 item.InvType = (int)InventoryType.Object; 615 item.InvType = (int)InventoryType.Object;
906 616
907 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object); 617 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
908 if (folder != null) 618 if (folder != null)
909 item.Folder = folder.ID; 619 item.Folder = folder.ID;
910 else // oopsies 620 else // oopsies
911 item.Folder = UUID.Zero; 621 item.Folder = UUID.Zero;
912 622
913 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions()) 623 if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
914 { 624 {
915 item.BasePermissions = grp.RootPart.NextOwnerMask; 625 item.BasePermissions = grp.RootPart.NextOwnerMask;
916 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 626 item.CurrentPermissions = grp.RootPart.NextOwnerMask;
@@ -933,15 +643,304 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
933 643
934 if (m_scene.AddInventoryItem(item)) 644 if (m_scene.AddInventoryItem(item))
935 { 645 {
936 remoteClient.SendInventoryItemCreateUpdate(item, 0); 646 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
937 } 647 }
938 else 648 else
939 { 649 {
940 if (m_dialogModule != null) 650 if (m_dialogModule != null)
941 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed"); 651 m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
942 } 652 }
943 653
944 return item; 654 return item;
945 } 655 }
656
657 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
658 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
659 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, UUID itemID)
660 {
661 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
662
663 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
664 return;
665
666 // We can NOT use the dictionries here, as we are looking
667 // for an entity by the fromAssetID, which is NOT the prim UUID
668 EntityBase[] detachEntities = m_scene.GetEntities();
669 SceneObjectGroup group;
670
671 lock (sp.AttachmentsSyncLock)
672 {
673 foreach (EntityBase entity in detachEntities)
674 {
675 if (entity is SceneObjectGroup)
676 {
677 group = (SceneObjectGroup)entity;
678 if (group.GetFromItemID() == itemID)
679 {
680 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
681 sp.RemoveAttachment(group);
682
683 // Prepare sog for storage
684 group.AttachedAvatar = UUID.Zero;
685 group.RootPart.SetParentLocalId(0);
686 group.IsAttachment = false;
687 group.AbsolutePosition = group.RootPart.AttachedPos;
688
689 UpdateKnownItem(sp, group);
690 m_scene.DeleteSceneObject(group, false);
691
692 return;
693 }
694 }
695 }
696 }
697 }
698
699 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
700 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
701 {
702 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
703 if (invAccess != null)
704 {
705 lock (sp.AttachmentsSyncLock)
706 {
707 SceneObjectGroup objatt;
708
709 if (itemID != UUID.Zero)
710 objatt = invAccess.RezObject(sp.ControllingClient,
711 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
712 false, false, sp.UUID, true);
713 else
714 objatt = invAccess.RezObject(sp.ControllingClient,
715 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
716 false, false, sp.UUID, true);
717
718 // m_log.DebugFormat(
719 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
720 // objatt.Name, remoteClient.Name, AttachmentPt);
721
722 if (objatt != null)
723 {
724 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
725 objatt.HasGroupChanged = false;
726 bool tainted = false;
727 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
728 tainted = true;
729
730 // This will throw if the attachment fails
731 try
732 {
733 AttachObject(sp, objatt, attachmentPt, false);
734 }
735 catch (Exception e)
736 {
737 m_log.ErrorFormat(
738 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
739 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
740
741 // Make sure the object doesn't stick around and bail
742 sp.RemoveAttachment(objatt);
743 m_scene.DeleteSceneObject(objatt, false);
744 return null;
745 }
746
747 if (tainted)
748 objatt.HasGroupChanged = true;
749
750 // Fire after attach, so we don't get messy perms dialogs
751 // 4 == AttachedRez
752 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
753 objatt.ResumeScripts();
754
755 // Do this last so that event listeners have access to all the effects of the attachment
756 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
757
758 return objatt;
759 }
760 else
761 {
762 m_log.WarnFormat(
763 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
764 itemID, sp.Name, attachmentPt);
765 }
766
767 if (doc != null)
768 {
769 objatt.LoadScriptState(doc);
770 objatt.ResetOwnerChangeFlag();
771 }
772
773 // Fire after attach, so we don't get messy perms dialogs
774 // 4 == AttachedRez
775 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
776 objatt.ResumeScripts();
777
778 // Do this last so that event listeners have access to all the effects of the attachment
779 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
780 }
781 }
782
783 return null;
784 }
785
786 /// <summary>
787 /// Update the user inventory to reflect an attachment
788 /// </summary>
789 /// <param name="sp"></param>
790 /// <param name="AttachmentPt"></param>
791 /// <param name="itemID"></param>
792 /// <param name="att"></param>
793 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
794 {
795 // m_log.DebugFormat(
796 // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
797 // att.Name, sp.Name, AttachmentPt, itemID);
798
799 if (UUID.Zero == itemID)
800 {
801 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID.");
802 return;
803 }
804
805 if (0 == AttachmentPt)
806 {
807 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error attachment point.");
808 return;
809 }
810
811 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
812 item = m_scene.InventoryService.GetItem(item);
813 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
814 if (changed && m_scene.AvatarFactory != null)
815 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
816 }
817
818 #endregion
819
820 #region Client Event Handlers
821
822 private ISceneEntity Client_OnRezSingleAttachmentFromInv(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
823 {
824 if (!Enabled)
825 return null;
826
827 // m_log.DebugFormat(
828 // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
829 // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
830
831 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
832
833 if (sp == null)
834 {
835 m_log.ErrorFormat(
836 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
837 remoteClient.Name, remoteClient.AgentId);
838 return null;
839 }
840
841 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
842 }
843
844 private void Client_OnRezMultipleAttachmentsFromInv(IClientAPI remoteClient, List<KeyValuePair<UUID, uint>> rezlist)
845 {
846 if (!Enabled)
847 return;
848
849 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
850 if (sp != null)
851 RezMultipleAttachmentsFromInventory(sp, rezlist);
852 else
853 m_log.ErrorFormat(
854 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
855 remoteClient.Name, remoteClient.AgentId);
856 }
857
858 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
859 {
860 // m_log.DebugFormat(
861 // "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
862 // objectLocalID, remoteClient.Name, AttachmentPt, silent);
863
864 if (!Enabled)
865 return;
866
867 try
868 {
869 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
870
871 if (sp == null)
872 {
873 m_log.ErrorFormat(
874 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
875 return;
876 }
877
878 // If we can't take it, we can't attach it!
879 SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID);
880 if (part == null)
881 return;
882
883 if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId))
884 {
885 remoteClient.SendAgentAlertMessage(
886 "You don't have sufficient permissions to attach this object", false);
887
888 return;
889 }
890
891 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
892 // be removed when that functionality is implemented in opensim
893 AttachmentPt &= 0x7f;
894
895 // Calls attach with a Zero position
896 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))
897 {
898 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
899
900 // Save avatar attachment information
901 m_log.Debug(
902 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
903 + ", AttachmentPoint: " + AttachmentPt);
904
905 }
906 }
907 catch (Exception e)
908 {
909 m_log.ErrorFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}{1}", e.Message, e.StackTrace);
910 }
911 }
912
913 private void Client_OnObjectDetach(uint objectLocalID, IClientAPI remoteClient)
914 {
915 if (!Enabled)
916 return;
917
918 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
919 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
920 if (sp != null && group != null)
921 DetachSingleAttachmentToInv(sp, group.GetFromItemID());
922 }
923
924 private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient)
925 {
926 if (!Enabled)
927 return;
928
929 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
930 if (sp != null)
931 DetachSingleAttachmentToInv(sp, itemID);
932 }
933
934 private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient)
935 {
936 if (!Enabled)
937 return;
938
939 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
940 if (sp != null)
941 DetachSingleAttachmentToGround(sp, soLocalId);
942 }
943
944 #endregion
946 } 945 }
947} 946}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 832c6eb..86cfb32 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -209,7 +209,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
209 209
210 m_attMod.RezSingleAttachmentFromInventory( 210 m_attMod.RezSingleAttachmentFromInventory(
211 m_presence, attItemId, (uint)AttachmentPoint.Chest); 211 m_presence, attItemId, (uint)AttachmentPoint.Chest);
212 m_attMod.DetachSingleAttachmentToInv(attItemId, m_presence.ControllingClient); 212 m_attMod.DetachSingleAttachmentToInv(m_presence, attItemId);
213 213
214 // Check status on scene presence 214 // Check status on scene presence
215 Assert.That(m_presence.HasAttachments(), Is.False); 215 Assert.That(m_presence.HasAttachments(), Is.False);
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index e2a3fa7..a7770ad 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -29,7 +29,6 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using OpenSim.Framework; 32using OpenSim.Framework;
34using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
35 34
@@ -41,6 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
41 /// RezAttachments. This should only be called upon login on the first region. 40 /// RezAttachments. This should only be called upon login on the first region.
42 /// Attachment rezzings on crossings and TPs are done in a different way. 41 /// Attachment rezzings on crossings and TPs are done in a different way.
43 /// </summary> 42 /// </summary>
43 /// <param name="sp"></param>
44 void RezAttachments(IScenePresence sp); 44 void RezAttachments(IScenePresence sp);
45 45
46 /// <summary> 46 /// <summary>
@@ -51,17 +51,16 @@ namespace OpenSim.Region.Framework.Interfaces
51 51
52 /// <summary> 52 /// <summary>
53 /// Delete all the presence's attachments from the scene 53 /// Delete all the presence's attachments from the scene
54 /// </summary>
55 /// <param name="sp">
56 /// This is done when a root agent leaves/is demoted to child (for instance, on logout, teleport or region cross). 54 /// This is done when a root agent leaves/is demoted to child (for instance, on logout, teleport or region cross).
57 /// </param> 55 /// </summary>
56 /// <param name="sp"></param>
58 /// <param name="silent"></param> 57 /// <param name="silent"></param>
59 void DeleteAttachmentsFromScene(IScenePresence sp, bool silent); 58 void DeleteAttachmentsFromScene(IScenePresence sp, bool silent);
60 59
61 /// <summary> 60 /// <summary>
62 /// Attach an object to an avatar 61 /// Attach an object to an avatar
63 /// </summary> 62 /// </summary>
64 /// <param name="remoteClient"></param> 63 /// <param name="sp"></param>
65 /// <param name="grp"></param> 64 /// <param name="grp"></param>
66 /// <param name="AttachmentPt"></param> 65 /// <param name="AttachmentPt"></param>
67 /// <param name="silent"></param> 66 /// <param name="silent"></param>
@@ -79,44 +78,28 @@ namespace OpenSim.Region.Framework.Interfaces
79 78
80 // Same as above, but also load script states from a separate doc 79 // Same as above, but also load script states from a separate doc
81 ISceneEntity RezSingleAttachmentFromInventory( 80 ISceneEntity RezSingleAttachmentFromInventory(
82 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc); 81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
83 82
84 /// <summary> 83 /// <summary>
85 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
86 /// </summary> 85 /// </summary>
87 /// <param name="sp"></param> 86 /// <param name="sp"></param>
88 /// <param name="header"></param> 87 /// <param name="rezlist"></param>
89 /// <param name="objects"></param>
90 void RezMultipleAttachmentsFromInventory(IScenePresence sp,List<KeyValuePair<UUID, uint>> rezlist); 88 void RezMultipleAttachmentsFromInventory(IScenePresence sp,List<KeyValuePair<UUID, uint>> rezlist);
91
92 /// <summary>
93 /// Detach an object from the avatar.
94 /// </summary>
95 /// <remarks>
96 /// This method is called in response to a client's detach request, so we only update the information in
97 /// inventory
98 /// </remarks>
99 /// <param name="objectLocalID"></param>
100 /// <param name="remoteClient"></param>
101 void DetachObject(uint objectLocalID, IClientAPI remoteClient);
102 89
103 /// <summary> 90 /// <summary>
104 /// Detach the given item to the ground. 91 /// Detach the given item to the ground.
105 /// </summary> 92 /// </summary>
106 /// <param name="sp"></param> 93 /// <param name="sp"></param>
107 /// <param name="objectLocalID"></param> 94 /// <param name="objectLocalID"></param>
108 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); 95 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
109 96
110 /// <summary> 97 /// <summary>
111 /// Detach the given item so that it remains in the user's inventory. 98 /// Detach the given item so that it remains in the user's inventory.
112 /// </summary> 99 /// </summary>
113 /// <param name="itemID"> 100 /// <param name="sp">/param>
114 /// A <see cref="UUID"/> 101 /// <param name="itemID"></param>
115 /// </param> 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
116 /// <param name="remoteClient">
117 /// A <see cref="IClientAPI"/>
118 /// </param>
119 void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient);
120 103
121 /// Update the position of an attachment. 104 /// Update the position of an attachment.
122 /// </summary> 105 /// </summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index fb595fe..03c1e12 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3316,7 +3316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3316 3316
3317 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3317 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3318 if (attachmentsModule != null) 3318 if (attachmentsModule != null)
3319 attachmentsModule.DetachSingleAttachmentToInv(itemID, presence.ControllingClient); 3319 attachmentsModule.DetachSingleAttachmentToInv(presence, itemID);
3320 } 3320 }
3321 3321
3322 public void llTakeCamera(string avatar) 3322 public void llTakeCamera(string avatar)