aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Attachments
diff options
context:
space:
mode:
authorMelanie2011-10-12 00:10:15 +0200
committerMelanie2011-10-12 00:10:15 +0200
commit1c2b5d99c9601a3d301f4bc0f53389cca831ee04 (patch)
tree97fa9c758f429d5dee64234e442f2c83cd1b9994 /OpenSim/Region/CoreModules/Avatar/Attachments
parentMerge branch 'careminster-presence-refactor' into bigmerge (diff)
parentMerge commit '92c88121c72386f85472c6cf4891eca8b62b9867' into bigmerge (diff)
downloadopensim-SC-1c2b5d99c9601a3d301f4bc0f53389cca831ee04.zip
opensim-SC-1c2b5d99c9601a3d301f4bc0f53389cca831ee04.tar.gz
opensim-SC-1c2b5d99c9601a3d301f4bc0f53389cca831ee04.tar.bz2
opensim-SC-1c2b5d99c9601a3d301f4bc0f53389cca831ee04.tar.xz
Merge branch 'bigmerge' of ssh://3dhosting.de/var/git/careminster into bigmerge
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs876
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs12
2 files changed, 457 insertions, 431 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a130ed2..09781c7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -45,29 +45,47 @@ 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;
51 private IDialogModule m_dialogModule; 52 private IDialogModule m_dialogModule;
53
54 /// <summary>
55 /// Are attachments enabled?
56 /// </summary>
57 public bool Enabled { get; private set; }
52 58
53 public string Name { get { return "Attachments Module"; } } 59 public string Name { get { return "Attachments Module"; } }
54 public Type ReplaceableInterface { get { return null; } } 60 public Type ReplaceableInterface { get { return null; } }
55 61
56 public void Initialise(IConfigSource source) {} 62 public void Initialise(IConfigSource source)
63 {
64 IConfig config = source.Configs["Attachments"];
65 if (config != null)
66 Enabled = config.GetBoolean("Enabled", true);
67 else
68 Enabled = true;
69 }
57 70
58 public void AddRegion(Scene scene) 71 public void AddRegion(Scene scene)
59 { 72 {
60 m_scene = scene; 73 m_scene = scene;
61 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>(); 74 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
62 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 75 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
63 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 76
77 if (Enabled)
78 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
79
64 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 80 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
65 } 81 }
66 82
67 public void RemoveRegion(Scene scene) 83 public void RemoveRegion(Scene scene)
68 { 84 {
69 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this); 85 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this);
70 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 86
87 if (Enabled)
88 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
71 } 89 }
72 90
73 public void RegionLoaded(Scene scene) {} 91 public void RegionLoaded(Scene scene) {}
@@ -76,26 +94,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
76 { 94 {
77 RemoveRegion(m_scene); 95 RemoveRegion(m_scene);
78 } 96 }
79 97
80 public void SubscribeToClientEvents(IClientAPI client) 98 #endregion
81 { 99
82 client.OnRezSingleAttachmentFromInv += RezSingleAttachmentFromInventory; 100 #region IAttachmentsModule
83 client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachmentsFromInventory;
84 client.OnObjectAttach += AttachObject;
85 client.OnObjectDetach += DetachObject;
86 client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv;
87 client.OnObjectDrop += DetachSingleAttachmentToGround;
88 }
89
90 public void UnsubscribeFromClientEvents(IClientAPI client)
91 {
92 client.OnRezSingleAttachmentFromInv -= RezSingleAttachmentFromInventory;
93 client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachmentsFromInventory;
94 client.OnObjectAttach -= AttachObject;
95 client.OnObjectDetach -= DetachObject;
96 client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv;
97 client.OnObjectDrop -= DetachSingleAttachmentToGround;
98 }
99 101
100 /// <summary> 102 /// <summary>
101 /// 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.
@@ -103,6 +105,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
103 /// </summary> 105 /// </summary>
104 public void RezAttachments(IScenePresence sp) 106 public void RezAttachments(IScenePresence sp)
105 { 107 {
108 if (!Enabled)
109 return;
110
106 if (null == sp.Appearance) 111 if (null == sp.Appearance)
107 { 112 {
108 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); 113 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
@@ -133,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
133 if (sp.PresenceType == PresenceType.Npc) 138 if (sp.PresenceType == PresenceType.Npc)
134 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null); 139 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null);
135 else 140 else
136 RezSingleAttachmentFromInventory(sp.ControllingClient, attach.ItemID, p); 141 RezSingleAttachmentFromInventory(sp, attach.ItemID, p);
137 } 142 }
138 catch (Exception e) 143 catch (Exception e)
139 { 144 {
@@ -146,13 +151,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
146 { 151 {
147// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); 152// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
148 153
154 if (!Enabled)
155 return;
156
149 foreach (SceneObjectGroup grp in sp.GetAttachments()) 157 foreach (SceneObjectGroup grp in sp.GetAttachments())
150 { 158 {
151// if (grp.HasGroupChanged) // Resizer scripts? 159// if (grp.HasGroupChanged) // Resizer scripts?
152// { 160// {
153 grp.IsAttachment = false; 161 grp.IsAttachment = false;
154 grp.AbsolutePosition = grp.RootPart.AttachedPos; 162 grp.AbsolutePosition = grp.RootPart.AttachedPos;
155 UpdateKnownItem(sp.ControllingClient, grp); 163 UpdateKnownItem(sp, grp);
156 grp.IsAttachment = true; 164 grp.IsAttachment = true;
157// } 165// }
158 } 166 }
@@ -164,6 +172,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
164// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", 172// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
165// m_scene.RegionInfo.RegionName, sp.Name, silent); 173// m_scene.RegionInfo.RegionName, sp.Name, silent);
166 174
175 if (!Enabled)
176 return;
177
167 foreach (SceneObjectGroup sop in sp.GetAttachments()) 178 foreach (SceneObjectGroup sop in sp.GetAttachments())
168 { 179 {
169 sop.Scene.DeleteSceneObject(sop, silent); 180 sop.Scene.DeleteSceneObject(sop, silent);
@@ -172,87 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
172 sp.ClearAttachments(); 183 sp.ClearAttachments();
173 } 184 }
174 185
175 /// <summary> 186 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
176 /// Called by client
177 /// </summary>
178 /// <param name="remoteClient"></param>
179 /// <param name="objectLocalID"></param>
180 /// <param name="AttachmentPt"></param>
181 /// <param name="silent"></param>
182 public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
183 {
184// m_log.DebugFormat(
185// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
186// objectLocalID, remoteClient.Name, AttachmentPt, silent);
187
188 try
189 {
190 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
191
192 if (sp == null)
193 {
194 m_log.ErrorFormat(
195 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
196 return;
197 }
198
199 // If we can't take it, we can't attach it!
200 SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID);
201 if (part == null)
202 return;
203
204 if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId))
205 {
206 remoteClient.SendAgentAlertMessage(
207 "You don't have sufficient permissions to attach this object", false);
208
209 return;
210 }
211
212 if (part.OwnerID != remoteClient.AgentId) // Not ours
213 {
214 remoteClient.SendAgentAlertMessage(
215 "You don't have sufficient permissions to attach this object", false);
216 return;
217 }
218
219 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
220 // be removed when that functionality is implemented in opensim
221 AttachmentPt &= 0x7f;
222
223 // Calls attach with a Zero position
224 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))
225 {
226 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
227
228 // Save avatar attachment information
229 m_log.Debug(
230 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
231 + ", AttachmentPoint: " + AttachmentPt);
232
233 }
234 }
235 catch (Exception e)
236 {
237 m_log.ErrorFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}{1}", e.Message, e.StackTrace);
238 }
239 }
240
241 public bool AttachObject(IClientAPI remoteClient, SceneObjectGroup group, uint AttachmentPt, bool silent)
242 {
243 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
244
245 if (sp == null)
246 {
247 m_log.ErrorFormat(
248 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
249 return false;
250 }
251
252 return AttachObject(sp, group, AttachmentPt, silent);
253 }
254
255 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
256 { 187 {
257 lock (sp.AttachmentsSyncLock) 188 lock (sp.AttachmentsSyncLock)
258 { 189 {
@@ -313,7 +244,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
313 UUID oldAttachmentItemID = attachments[0].GetFromItemID(); 244 UUID oldAttachmentItemID = attachments[0].GetFromItemID();
314 245
315 if (oldAttachmentItemID != UUID.Zero) 246 if (oldAttachmentItemID != UUID.Zero)
316 DetachSingleAttachmentToInv(oldAttachmentItemID, sp); 247 DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
317 else 248 else
318 m_log.WarnFormat( 249 m_log.WarnFormat(
319 "[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!",
@@ -323,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
323 // 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.
324 UUID newAttachmentItemID = group.GetFromItemID(); 255 UUID newAttachmentItemID = group.GetFromItemID();
325 if (newAttachmentItemID == UUID.Zero) 256 if (newAttachmentItemID == UUID.Zero)
326 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; 257 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
327 258
328 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 259 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
329 } 260 }
@@ -334,55 +265,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
334 return true; 265 return true;
335 } 266 }
336 267
337 public void RezMultipleAttachmentsFromInventory( 268 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
338 IClientAPI remoteClient, 269 {
339 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, 270 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null);
340 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) 271 }
341 {
342 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
343
344 if (sp == null)
345 {
346 m_log.ErrorFormat(
347 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
348 remoteClient.Name, remoteClient.AgentId);
349 return;
350 }
351
352 lock (sp.AttachmentsSyncLock)
353 {
354// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
355
356 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects)
357 {
358 RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt);
359 }
360 }
361 }
362
363 public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
364 {
365 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
366 }
367 272
368 public ISceneEntity RezSingleAttachmentFromInventory( 273 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
369 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
370 { 274 {
371 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 275 if (!Enabled)
372
373 if (sp == null)
374 {
375 m_log.ErrorFormat(
376 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
377 remoteClient.Name, remoteClient.AgentId);
378 return null; 276 return null;
379 }
380
381 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
382 }
383 277
384 public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt)
385 {
386// m_log.DebugFormat( 278// m_log.DebugFormat(
387// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", 279// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
388// (AttachmentPoint)AttachmentPt, itemID, sp.Name); 280// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
@@ -417,188 +309,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
417 return null; 309 return null;
418 } 310 }
419 311
420 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, null); 312 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
421 313
422 if (att == null) 314 if (att == null)
423 DetachSingleAttachmentToInv(itemID, sp.ControllingClient); 315 DetachSingleAttachmentToInv(sp, itemID);
424 316
425 return att; 317 return att;
426 } 318 }
427 319
428 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 320 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
429 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
430 {
431 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
432 if (invAccess != null)
433 {
434 lock (sp.AttachmentsSyncLock)
435 {
436 SceneObjectGroup objatt;
437
438 if (itemID != UUID.Zero)
439 objatt = invAccess.RezObject(sp.ControllingClient,
440 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
441 false, false, sp.UUID, true);
442 else
443 objatt = invAccess.RezObject(sp.ControllingClient,
444 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
445 false, false, sp.UUID, true);
446
447 // m_log.DebugFormat(
448 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
449 // objatt.Name, remoteClient.Name, AttachmentPt);
450
451 if (objatt != null)
452 {
453 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
454 objatt.HasGroupChanged = false;
455 bool tainted = false;
456 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
457 tainted = true;
458
459 // This will throw if the attachment fails
460 try
461 {
462 AttachObject(sp, objatt, attachmentPt, false);
463 }
464 catch (Exception e)
465 {
466 m_log.ErrorFormat(
467 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
468 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
469
470 // Make sure the object doesn't stick around and bail
471 sp.RemoveAttachment(objatt);
472 m_scene.DeleteSceneObject(objatt, false);
473 return null;
474 }
475
476 if (tainted)
477 objatt.HasGroupChanged = true;
478
479 // Fire after attach, so we don't get messy perms dialogs
480 // 4 == AttachedRez
481 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
482 objatt.ResumeScripts();
483
484 // Do this last so that event listeners have access to all the effects of the attachment
485 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
486
487 return objatt;
488 }
489 else
490 {
491 m_log.WarnFormat(
492 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
493 itemID, sp.Name, attachmentPt);
494 }
495
496 if (doc != null)
497 {
498 objatt.LoadScriptState(doc);
499 objatt.ResetOwnerChangeFlag();
500 }
501
502 // Fire after attach, so we don't get messy perms dialogs
503 // 4 == AttachedRez
504 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
505 objatt.ResumeScripts();
506
507 // Do this last so that event listeners have access to all the effects of the attachment
508 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
509 }
510 }
511
512 return null;
513 }
514
515 /// <summary>
516 /// Update the user inventory to reflect an attachment
517 /// </summary>
518 /// <param name="sp"></param>
519 /// <param name="AttachmentPt"></param>
520 /// <param name="itemID"></param>
521 /// <param name="att"></param>
522 private void ShowAttachInUserInventory(
523 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
524 { 321 {
525// m_log.DebugFormat( 322 if (!Enabled)
526// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
527// att.Name, sp.Name, AttachmentPt, itemID);
528
529 if (UUID.Zero == itemID)
530 {
531 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID.");
532 return;
533 }
534
535 if (0 == AttachmentPt)
536 {
537 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error attachment point.");
538 return;
539 }
540
541 if (null == att.RootPart)
542 {
543 m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment for a prim without the rootpart!");
544 return; 323 return;
545 }
546 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
547
548
549
550
551
552
553 item = m_scene.InventoryService.GetItem(item);
554 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
555 if (changed && m_scene.AvatarFactory != null)
556 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
557 }
558 324
559 public void DetachObject(uint objectLocalID, IClientAPI remoteClient) 325 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
560 { 326 lock (sp.AttachmentsSyncLock)
561// m_log.DebugFormat(
562// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
563
564 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
565 if (group != null)
566 {
567 DetachSingleAttachmentToInv(group.GetFromItemID(), remoteClient);
568 }
569 }
570
571 public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient)
572 {
573 ScenePresence presence;
574 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
575 { 327 {
576 lock (presence.AttachmentsSyncLock) 328 foreach (KeyValuePair<UUID, uint> rez in rezlist)
577 { 329 {
578 // Save avatar attachment information 330 RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value);
579 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
580
581 bool changed = presence.Appearance.DetachAttachment(itemID);
582 if (changed && m_scene.AvatarFactory != null)
583 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
584
585 DetachSingleAttachmentToInv(itemID, presence);
586 } 331 }
587 } 332 }
588 } 333 }
589 334
590 public void DetachSingleAttachmentToGround(uint soLocalId, IClientAPI remoteClient) 335 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
591 { 336 {
337 if (!Enabled)
338 return;
339
592// m_log.DebugFormat( 340// m_log.DebugFormat(
593// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 341// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
594// remoteClient.Name, soLocalId); 342// sp.UUID, soLocalId);
595 343
596 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 344 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
597 345
598 if (so == null) 346 if (so == null)
599 return; 347 return;
600 348
601 if (so.AttachedAvatar != remoteClient.AgentId) 349 if (so.AttachedAvatar != sp.UUID)
602 return; 350 return;
603 351
604 UUID inventoryID = so.GetFromItemID(); 352 UUID inventoryID = so.GetFromItemID();
@@ -607,103 +355,62 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
607// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", 355// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
608// so.Name, so.LocalId, inventoryID); 356// so.Name, so.LocalId, inventoryID);
609 357
610 ScenePresence presence; 358 lock (sp.AttachmentsSyncLock)
611 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
612 { 359 {
613 lock (presence.AttachmentsSyncLock) 360 if (!m_scene.Permissions.CanRezObject(
614 { 361 so.PrimCount, sp.UUID, sp.AbsolutePosition))
615 if (!m_scene.Permissions.CanRezObject( 362 return;
616 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
617 return;
618
619 bool changed = presence.Appearance.DetachAttachment(inventoryID);
620 if (changed && m_scene.AvatarFactory != null)
621 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
622
623 presence.RemoveAttachment(so);
624 DetachSceneObjectToGround(so, presence);
625
626 List<UUID> uuids = new List<UUID>();
627 uuids.Add(inventoryID);
628 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
629 remoteClient.SendRemoveInventoryItem(inventoryID);
630 }
631 363
632 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 364 bool changed = sp.Appearance.DetachAttachment(inventoryID);
365 if (changed && m_scene.AvatarFactory != null)
366 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
367
368 sp.RemoveAttachment(so);
369
370 SceneObjectPart rootPart = so.RootPart;
371 rootPart.FromItemID = UUID.Zero;
372 so.AbsolutePosition = sp.AbsolutePosition;
373 so.AttachedAvatar = UUID.Zero;
374 rootPart.SetParentLocalId(0);
375 so.ClearPartAttachmentData();
376 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
377 so.HasGroupChanged = true;
378 rootPart.Rezzed = DateTime.Now;
379 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
380 so.AttachToBackup();
381 m_scene.EventManager.TriggerParcelPrimCountTainted();
382 rootPart.ScheduleFullUpdate();
383 rootPart.ClearUndoState();
384
385 List<UUID> uuids = new List<UUID>();
386 uuids.Add(inventoryID);
387 m_scene.InventoryService.DeleteItems(sp.UUID, uuids);
388 sp.ControllingClient.SendRemoveInventoryItem(inventoryID);
633 } 389 }
634 }
635 390
636 /// <summary> 391 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
637 /// Detach the given scene object to the ground.
638 /// </summary>
639 /// <remarks>
640 /// The caller has to take care of all the other work in updating avatar appearance, inventory, etc.
641 /// </remarks>
642 /// <param name="so">The scene object to detach.</param>
643 /// <param name="sp">The scene presence from which the scene object is being detached.</param>
644 private void DetachSceneObjectToGround(SceneObjectGroup so, ScenePresence sp)
645 {
646 SceneObjectPart rootPart = so.RootPart;
647
648 rootPart.FromItemID = UUID.Zero;
649 so.AbsolutePosition = sp.AbsolutePosition;
650 so.AttachedAvatar = UUID.Zero;
651 rootPart.SetParentLocalId(0);
652 so.ClearPartAttachmentData();
653 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
654 so.HasGroupChanged = true;
655 rootPart.Rezzed = DateTime.Now;
656 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
657 so.AttachToBackup();
658 m_scene.EventManager.TriggerParcelPrimCountTainted();
659 rootPart.ScheduleFullUpdate();
660 rootPart.ClearUndoState();
661 } 392 }
662
663 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
664 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
665 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
666 {
667// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
668
669 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
670 return;
671
672 // We can NOT use the dictionries here, as we are looking
673 // for an entity by the fromAssetID, which is NOT the prim UUID
674 EntityBase[] detachEntities = m_scene.GetEntities();
675 SceneObjectGroup group;
676 393
394 public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID)
395 {
677 lock (sp.AttachmentsSyncLock) 396 lock (sp.AttachmentsSyncLock)
678 { 397 {
679 foreach (EntityBase entity in detachEntities) 398 // Save avatar attachment information
680 { 399 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
681 if (entity is SceneObjectGroup)
682 {
683 group = (SceneObjectGroup)entity; if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
684 // CM / XMREngine!!!! Needed to conclude attach event
685 //SceneObjectSerializer.ToOriginalXmlFormat(group);
686 group.DetachToInventoryPrep();
687 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
688 400
689 // Prepare sog for storage 401 bool changed = sp.Appearance.DetachAttachment(itemID);
690 group.AttachedAvatar = UUID.Zero; 402 if (changed && m_scene.AvatarFactory != null)
691 group.RootPart.SetParentLocalId(0); 403 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
692 group.IsAttachment = false;
693 group.AbsolutePosition = group.RootPart.AttachedPos;
694
695 UpdateKnownItem(sp.ControllingClient, group);
696 m_scene.DeleteSceneObject(group, false);
697 404
698 return; 405 DetachSingleAttachmentToInvInternal(sp, itemID);
699 }
700 }
701 }
702 } 406 }
703 } 407 }
704 408
705 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) 409 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos)
706 { 410 {
411 if (!Enabled)
412 return;
413
707 // First we save the 414 // First we save the
708 // attachment point information, then we update the relative 415 // attachment point information, then we update the relative
709 // positioning. Then we have to mark the object as NOT an 416 // positioning. Then we have to mark the object as NOT an
@@ -717,7 +424,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
717 sog.AttachmentPoint = attachmentPoint; 424 sog.AttachmentPoint = attachmentPoint;
718 sog.HasGroupChanged = true; 425 sog.HasGroupChanged = true;
719 } 426 }
720 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
721 /// <summary> 458 /// <summary>
722 /// 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.
723 /// </summary> 460 /// </summary>
@@ -725,9 +462,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
725 /// 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,
726 /// these details are not stored on the region. 463 /// these details are not stored on the region.
727 /// </remarks> 464 /// </remarks>
728 /// <param name="remoteClient"></param> 465 /// <param name="sp"></param>
729 /// <param name="grp"></param> 466 /// <param name="grp"></param>
730 private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp) 467 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp)
731 { 468 {
732 if (grp.HasGroupChanged || grp.ContainsScripts()) 469 if (grp.HasGroupChanged || grp.ContainsScripts())
733 { 470 {
@@ -737,7 +474,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
737 474
738 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 475 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
739 476
740 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId); 477 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), sp.UUID);
741 item = m_scene.InventoryService.GetItem(item); 478 item = m_scene.InventoryService.GetItem(item);
742 479
743 if (item != null) 480 if (item != null)
@@ -747,7 +484,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
747 grp.GetPartDescription(grp.LocalId), 484 grp.GetPartDescription(grp.LocalId),
748 (sbyte)AssetType.Object, 485 (sbyte)AssetType.Object,
749 Utils.StringToBytes(sceneObjectXml), 486 Utils.StringToBytes(sceneObjectXml),
750 remoteClient.AgentId); 487 sp.UUID);
751 m_scene.AssetService.Store(asset); 488 m_scene.AssetService.Store(asset);
752 489
753 item.AssetID = asset.FullID; 490 item.AssetID = asset.FullID;
@@ -759,8 +496,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
759 m_scene.InventoryService.UpdateItem(item); 496 m_scene.InventoryService.UpdateItem(item);
760 497
761 // this gets called when the agent logs off! 498 // this gets called when the agent logs off!
762 if (remoteClient != null) 499 if (sp.ControllingClient != null)
763 remoteClient.SendInventoryItemCreateUpdate(item, 0); 500 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
764 } 501 }
765 } 502 }
766 else 503 else
@@ -769,8 +506,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
769 "[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}",
770 grp.UUID, grp.AttachmentPoint); 507 grp.UUID, grp.AttachmentPoint);
771 } 508 }
772 } 509 }
773 510
774 /// <summary> 511 /// <summary>
775 /// Attach this scene object to the given avatar. 512 /// Attach this scene object to the given avatar.
776 /// </summary> 513 /// </summary>
@@ -784,19 +521,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
784 /// <param name="attachOffset"></param> 521 /// <param name="attachOffset"></param>
785 /// <param name="silent"></param> 522 /// <param name="silent"></param>
786 private void AttachToAgent( 523 private void AttachToAgent(
787 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 524 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
788 { 525 {
789// m_log.DebugFormat( 526 // m_log.DebugFormat(
790// "[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}",
791// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 528 // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
792 529
793 so.DetachFromBackup(); 530 so.DetachFromBackup();
794 531
795 // Remove from database and parcel prim count 532 // Remove from database and parcel prim count
796 m_scene.DeleteFromStorage(so.UUID); 533 m_scene.DeleteFromStorage(so.UUID);
797 m_scene.EventManager.TriggerParcelPrimCountTainted(); 534 m_scene.EventManager.TriggerParcelPrimCountTainted();
798 535
799 so.AttachedAvatar = avatar.UUID; 536 so.AttachedAvatar = sp.UUID;
800 537
801 if (so.RootPart.PhysActor != null) 538 if (so.RootPart.PhysActor != null)
802 { 539 {
@@ -807,17 +544,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
807 so.AbsolutePosition = attachOffset; 544 so.AbsolutePosition = attachOffset;
808 so.RootPart.AttachedPos = attachOffset; 545 so.RootPart.AttachedPos = attachOffset;
809 so.IsAttachment = true; 546 so.IsAttachment = true;
810 so.RootPart.SetParentLocalId(avatar.LocalId); 547 so.RootPart.SetParentLocalId(sp.LocalId);
811 so.AttachmentPoint = attachmentpoint; 548 so.AttachmentPoint = attachmentpoint;
812 549
813 avatar.AddAttachment(so); 550 sp.AddAttachment(so);
814 551
815 if (!silent) 552 if (!silent)
816 { 553 {
817 so.IsSelected = false; // fudge.... 554 so.IsSelected = false; // fudge....
818 so.ScheduleGroupForFullUpdate(); 555 so.ScheduleGroupForFullUpdate();
819 } 556 }
820 557
821 // In case it is later dropped again, don't let 558 // In case it is later dropped again, don't let
822 // it get cleaned up 559 // it get cleaned up
823 so.RootPart.RemFlag(PrimFlags.TemporaryOnRez); 560 so.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
@@ -829,19 +566,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
829 /// <param name="remoteClient"></param> 566 /// <param name="remoteClient"></param>
830 /// <param name="grp"></param> 567 /// <param name="grp"></param>
831 /// <returns>The user inventory item created that holds the attachment.</returns> 568 /// <returns>The user inventory item created that holds the attachment.</returns>
832 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) 569 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
833 { 570 {
834// m_log.DebugFormat( 571 // m_log.DebugFormat(
835// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 572 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
836// grp.Name, grp.LocalId, remoteClient.Name); 573 // grp.Name, grp.LocalId, remoteClient.Name);
837 uint regionSize = Constants.RegionSize; //Avoid VS error "The operation overflows at compile time in checked mode" 574
838 Vector3 inventoryStoredPosition = new Vector3 575 Vector3 inventoryStoredPosition = new Vector3
839 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 576 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
840 ? regionSize - 6 577 ? (float)Constants.RegionSize - 6
841 : grp.AbsolutePosition.X) 578 : grp.AbsolutePosition.X)
842 , 579 ,
843 (grp.AbsolutePosition.Y > (int)Constants.RegionSize) 580 (grp.AbsolutePosition.Y > (int)Constants.RegionSize)
844 ? regionSize - 6 581 ? (float)Constants.RegionSize - 6
845 : grp.AbsolutePosition.Y, 582 : grp.AbsolutePosition.Y,
846 grp.AbsolutePosition.Z); 583 grp.AbsolutePosition.Z);
847 584
@@ -862,14 +599,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
862 grp.GetPartDescription(grp.LocalId), 599 grp.GetPartDescription(grp.LocalId),
863 (sbyte)AssetType.Object, 600 (sbyte)AssetType.Object,
864 Utils.StringToBytes(sceneObjectXml), 601 Utils.StringToBytes(sceneObjectXml),
865 remoteClient.AgentId); 602 sp.UUID);
866 603
867 m_scene.AssetService.Store(asset); 604 m_scene.AssetService.Store(asset);
868 605
869 InventoryItemBase item = new InventoryItemBase(); 606 InventoryItemBase item = new InventoryItemBase();
870 item.CreatorId = grp.RootPart.CreatorID.ToString(); 607 item.CreatorId = grp.RootPart.CreatorID.ToString();
871 item.CreatorData = grp.RootPart.CreatorData; 608 item.CreatorData = grp.RootPart.CreatorData;
872 item.Owner = remoteClient.AgentId; 609 item.Owner = sp.UUID;
873 item.ID = UUID.Random(); 610 item.ID = UUID.Random();
874 item.AssetID = asset.FullID; 611 item.AssetID = asset.FullID;
875 item.Description = asset.Description; 612 item.Description = asset.Description;
@@ -877,13 +614,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
877 item.AssetType = asset.Type; 614 item.AssetType = asset.Type;
878 item.InvType = (int)InventoryType.Object; 615 item.InvType = (int)InventoryType.Object;
879 616
880 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object); 617 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
881 if (folder != null) 618 if (folder != null)
882 item.Folder = folder.ID; 619 item.Folder = folder.ID;
883 else // oopsies 620 else // oopsies
884 item.Folder = UUID.Zero; 621 item.Folder = UUID.Zero;
885 622
886 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions()) 623 if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
887 { 624 {
888 item.BasePermissions = grp.RootPart.NextOwnerMask; 625 item.BasePermissions = grp.RootPart.NextOwnerMask;
889 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 626 item.CurrentPermissions = grp.RootPart.NextOwnerMask;
@@ -906,15 +643,304 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
906 643
907 if (m_scene.AddInventoryItem(item)) 644 if (m_scene.AddInventoryItem(item))
908 { 645 {
909 remoteClient.SendInventoryItemCreateUpdate(item, 0); 646 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
910 } 647 }
911 else 648 else
912 { 649 {
913 if (m_dialogModule != null) 650 if (m_dialogModule != null)
914 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed"); 651 m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
915 } 652 }
916 653
917 return item; 654 return item;
918 } 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
919 } 945 }
920} \ No newline at end of file 946}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index ff3358f..86cfb32 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
106 106
107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup; 107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup;
108 108
109 m_attMod.AttachObject(m_presence.ControllingClient, so, (uint)AttachmentPoint.Chest, false); 109 m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false);
110 110
111 // Check status on scene presence 111 // Check status on scene presence
112 Assert.That(m_presence.HasAttachments(), Is.True); 112 Assert.That(m_presence.HasAttachments(), Is.True);
@@ -140,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
140 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 140 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
141 141
142 m_attMod.RezSingleAttachmentFromInventory( 142 m_attMod.RezSingleAttachmentFromInventory(
143 m_presence.ControllingClient, attItemId, (uint)AttachmentPoint.Chest); 143 m_presence, attItemId, (uint)AttachmentPoint.Chest);
144 144
145 // Check scene presence status 145 // Check scene presence status
146 Assert.That(m_presence.HasAttachments(), Is.True); 146 Assert.That(m_presence.HasAttachments(), Is.True);
@@ -174,8 +174,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
174 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 174 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
175 175
176 ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory( 176 ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory(
177 m_presence.ControllingClient, attItemId, (uint)AttachmentPoint.Chest); 177 m_presence, attItemId, (uint)AttachmentPoint.Chest);
178 m_attMod.DetachSingleAttachmentToGround(so.LocalId, m_presence.ControllingClient); 178 m_attMod.DetachSingleAttachmentToGround(m_presence, so.LocalId);
179 179
180 // Check scene presence status 180 // Check scene presence status
181 Assert.That(m_presence.HasAttachments(), Is.False); 181 Assert.That(m_presence.HasAttachments(), Is.False);
@@ -208,8 +208,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
208 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 208 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
209 209
210 m_attMod.RezSingleAttachmentFromInventory( 210 m_attMod.RezSingleAttachmentFromInventory(
211 m_presence.ControllingClient, 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);