diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 367 |
1 files changed, 261 insertions, 106 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2f67c4e..9f52a14 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -41,6 +41,8 @@ using OpenSim.Region.Framework; | |||
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
43 | using OpenSim.Region.Framework.Scenes.Serialization; | 43 | using OpenSim.Region.Framework.Scenes.Serialization; |
44 | using OpenSim.Services.Interfaces; | ||
45 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
44 | 46 | ||
45 | namespace OpenSim.Region.CoreModules.Avatar.Attachments | 47 | namespace OpenSim.Region.CoreModules.Avatar.Attachments |
46 | { | 48 | { |
@@ -60,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
60 | /// A value of 0 will apply no pause. The pause is specified in milliseconds. | 62 | /// A value of 0 will apply no pause. The pause is specified in milliseconds. |
61 | /// </remarks> | 63 | /// </remarks> |
62 | public int ThrottlePer100PrimsRezzed { get; set; } | 64 | public int ThrottlePer100PrimsRezzed { get; set; } |
63 | 65 | ||
64 | private Scene m_scene; | 66 | private Scene m_scene; |
65 | private IInventoryAccessModule m_invAccessModule; | 67 | private IInventoryAccessModule m_invAccessModule; |
66 | 68 | ||
@@ -68,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
68 | /// Are attachments enabled? | 70 | /// Are attachments enabled? |
69 | /// </summary> | 71 | /// </summary> |
70 | public bool Enabled { get; private set; } | 72 | public bool Enabled { get; private set; } |
71 | 73 | ||
72 | public string Name { get { return "Attachments Module"; } } | 74 | public string Name { get { return "Attachments Module"; } } |
73 | public Type ReplaceableInterface { get { return null; } } | 75 | public Type ReplaceableInterface { get { return null; } } |
74 | 76 | ||
@@ -86,14 +88,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
86 | Enabled = true; | 88 | Enabled = true; |
87 | } | 89 | } |
88 | } | 90 | } |
89 | 91 | ||
90 | public void AddRegion(Scene scene) | 92 | public void AddRegion(Scene scene) |
91 | { | 93 | { |
92 | m_scene = scene; | 94 | m_scene = scene; |
93 | if (Enabled) | 95 | if (Enabled) |
94 | { | 96 | { |
95 | // Only register module with scene if it is enabled. All callers check for a null attachments module. | 97 | // Only register module with scene if it is enabled. All callers check for a null attachments module. |
96 | // Ideally, there should be a null attachments module for when this core attachments module has been | 98 | // Ideally, there should be a null attachments module for when this core attachments module has been |
97 | // disabled. Registering only when enabled allows for other attachments module implementations. | 99 | // disabled. Registering only when enabled allows for other attachments module implementations. |
98 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); | 100 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); |
99 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 101 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
@@ -180,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
180 | private void HandleScriptStateChange(uint localID, bool started) | 182 | private void HandleScriptStateChange(uint localID, bool started) |
181 | { | 183 | { |
182 | SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); | 184 | SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); |
183 | if (sog != null && sog.IsAttachment) | 185 | if (sog != null && sog.IsAttachment) |
184 | { | 186 | { |
185 | if (!started) | 187 | if (!started) |
186 | { | 188 | { |
@@ -197,21 +199,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
197 | } | 199 | } |
198 | } | 200 | } |
199 | } | 201 | } |
200 | 202 | ||
201 | public void RemoveRegion(Scene scene) | 203 | public void RemoveRegion(Scene scene) |
202 | { | 204 | { |
203 | m_scene.UnregisterModuleInterface<IAttachmentsModule>(this); | 205 | m_scene.UnregisterModuleInterface<IAttachmentsModule>(this); |
204 | 206 | ||
205 | if (Enabled) | 207 | if (Enabled) |
206 | m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; | 208 | m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; |
207 | } | 209 | } |
208 | 210 | ||
209 | public void RegionLoaded(Scene scene) | 211 | public void RegionLoaded(Scene scene) |
210 | { | 212 | { |
211 | m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>(); | 213 | m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>(); |
212 | } | 214 | } |
213 | 215 | ||
214 | public void Close() | 216 | public void Close() |
215 | { | 217 | { |
216 | RemoveRegion(m_scene); | 218 | RemoveRegion(m_scene); |
217 | } | 219 | } |
@@ -269,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
269 | ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); | 271 | ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); |
270 | 272 | ||
271 | // m_log.DebugFormat( | 273 | // m_log.DebugFormat( |
272 | // "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", | 274 | // "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", |
273 | // ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); | 275 | // ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); |
274 | 276 | ||
275 | so.SetState(ad.AttachmentObjectStates[i++], m_scene); | 277 | so.SetState(ad.AttachmentObjectStates[i++], m_scene); |
@@ -294,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
294 | { | 296 | { |
295 | if (DebugLevel > 0) | 297 | if (DebugLevel > 0) |
296 | m_log.DebugFormat( | 298 | m_log.DebugFormat( |
297 | "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", | 299 | "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", |
298 | m_scene.Name, sp.Name); | 300 | m_scene.Name, sp.Name); |
299 | 301 | ||
300 | return; | 302 | return; |
@@ -303,6 +305,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
303 | if (DebugLevel > 0) | 305 | if (DebugLevel > 0) |
304 | m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); | 306 | m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); |
305 | 307 | ||
308 | XmlDocument doc = new XmlDocument(); | ||
309 | doc.XmlResolver=null; | ||
310 | string stateData = String.Empty; | ||
311 | |||
312 | IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>(); | ||
313 | if (attServ != null) | ||
314 | { | ||
315 | m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); | ||
316 | stateData = attServ.Get(sp.UUID.ToString()); | ||
317 | if (stateData != String.Empty) | ||
318 | { | ||
319 | try | ||
320 | { | ||
321 | doc.LoadXml(stateData); | ||
322 | } | ||
323 | catch { } | ||
324 | } | ||
325 | } | ||
326 | |||
327 | Dictionary<UUID, string> itemData = new Dictionary<UUID, string>(); | ||
328 | |||
329 | XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); | ||
330 | if (nodes.Count > 0) | ||
331 | { | ||
332 | foreach (XmlNode n in nodes) | ||
333 | { | ||
334 | XmlElement elem = (XmlElement)n; | ||
335 | string itemID = elem.GetAttribute("ItemID"); | ||
336 | string xml = elem.InnerXml; | ||
337 | |||
338 | itemData[new UUID(itemID)] = xml; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
306 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | 343 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); |
307 | 344 | ||
308 | // Let's get all items at once, so they get cached | 345 | // Let's get all items at once, so they get cached |
@@ -322,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
322 | 359 | ||
323 | // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down | 360 | // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down |
324 | // But they're not used anyway, the item is being looked up for now, so let's proceed. | 361 | // But they're not used anyway, the item is being looked up for now, so let's proceed. |
325 | //if (UUID.Zero == assetID) | 362 | //if (UUID.Zero == assetID) |
326 | //{ | 363 | //{ |
327 | // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); | 364 | // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); |
328 | // continue; | 365 | // continue; |
@@ -330,10 +367,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
330 | 367 | ||
331 | try | 368 | try |
332 | { | 369 | { |
370 | string xmlData; | ||
371 | XmlDocument d = null; | ||
372 | UUID asset; | ||
373 | if (itemData.TryGetValue(attach.ItemID, out xmlData)) | ||
374 | { | ||
375 | d = new XmlDocument(); | ||
376 | d.XmlResolver=null; | ||
377 | d.LoadXml(xmlData); | ||
378 | m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID); | ||
379 | } | ||
380 | |||
333 | // If we're an NPC then skip all the item checks and manipulations since we don't have an | 381 | // If we're an NPC then skip all the item checks and manipulations since we don't have an |
334 | // inventory right now. | 382 | // inventory right now. |
335 | RezSingleAttachmentFromInventoryInternal( | 383 | RezSingleAttachmentFromInventoryInternal( |
336 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); | 384 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d); |
337 | } | 385 | } |
338 | catch (Exception e) | 386 | catch (Exception e) |
339 | { | 387 | { |
@@ -361,26 +409,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
361 | 409 | ||
362 | Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); | 410 | Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); |
363 | 411 | ||
364 | foreach (SceneObjectGroup so in attachments) | 412 | |
413 | if (sp.PresenceType != PresenceType.Npc) | ||
365 | { | 414 | { |
366 | // Scripts MUST be snapshotted before the object is | 415 | foreach (SceneObjectGroup so in attachments) |
367 | // removed from the scene because doing otherwise will | 416 | { |
368 | // clobber the run flag | 417 | // Scripts MUST be snapshotted before the object is |
369 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from | 418 | // removed from the scene because doing otherwise will |
370 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | 419 | // clobber the run flag |
371 | scriptStates[so] = PrepareScriptInstanceForSave(so, false); | 420 | // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from |
421 | // scripts performing attachment operations at the same time. Getting object states stops the scripts. | ||
422 | scriptStates[so] = PrepareScriptInstanceForSave(so, false); | ||
423 | } | ||
372 | 424 | ||
373 | // m_log.DebugFormat( | 425 | lock (sp.AttachmentsSyncLock) |
374 | // "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}", | 426 | { |
375 | // so.Name, sp.Name, m_scene.Name, scriptStates[so]); | 427 | foreach (SceneObjectGroup so in attachments) |
428 | UpdateDetachedObject(sp, so, scriptStates[so]); | ||
429 | sp.ClearAttachments(); | ||
430 | } | ||
376 | } | 431 | } |
377 | 432 | else | |
378 | lock (sp.AttachmentsSyncLock) | ||
379 | { | 433 | { |
380 | foreach (SceneObjectGroup so in attachments) | 434 | lock (sp.AttachmentsSyncLock) |
381 | UpdateDetachedObject(sp, so, scriptStates[so]); | 435 | { |
382 | 436 | foreach (SceneObjectGroup so in attachments) | |
383 | sp.ClearAttachments(); | 437 | UpdateDetachedObject(sp, so, String.Empty); |
438 | sp.ClearAttachments(); | ||
439 | } | ||
384 | } | 440 | } |
385 | } | 441 | } |
386 | 442 | ||
@@ -392,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
392 | if (DebugLevel > 0) | 448 | if (DebugLevel > 0) |
393 | m_log.DebugFormat( | 449 | m_log.DebugFormat( |
394 | "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", | 450 | "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", |
395 | m_scene.RegionInfo.RegionName, sp.Name, silent); | 451 | m_scene.RegionInfo.RegionName, sp.Name, silent); |
396 | 452 | ||
397 | foreach (SceneObjectGroup sop in sp.GetAttachments()) | 453 | foreach (SceneObjectGroup sop in sp.GetAttachments()) |
398 | { | 454 | { |
@@ -401,21 +457,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
401 | 457 | ||
402 | sp.ClearAttachments(); | 458 | sp.ClearAttachments(); |
403 | } | 459 | } |
404 | 460 | ||
405 | public bool AttachObject( | 461 | public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, |
406 | IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append) | 462 | bool addToInventory, bool append) |
407 | { | 463 | { |
408 | if (!Enabled) | 464 | if (!Enabled) |
409 | return false; | 465 | return false; |
410 | 466 | ||
411 | group.DetachFromBackup(); | 467 | return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); |
412 | |||
413 | bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); | ||
414 | |||
415 | if (!success) | ||
416 | group.AttachToBackup(); | ||
417 | |||
418 | return success; | ||
419 | } | 468 | } |
420 | 469 | ||
421 | /// <summary> | 470 | /// <summary> |
@@ -428,10 +477,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
428 | /// <param name='silent'></param> | 477 | /// <param name='silent'></param> |
429 | /// <param name='addToInventory'>If true then add object to user inventory.</param> | 478 | /// <param name='addToInventory'>If true then add object to user inventory.</param> |
430 | /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> | 479 | /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> |
431 | /// <param name='append'>Append to attachment point rather than replace.</param> | 480 | private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, |
432 | private bool AttachObjectInternal( | 481 | bool silent, bool addToInventory, bool resumeScripts, bool append) |
433 | IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append) | ||
434 | { | 482 | { |
483 | // m_log.DebugFormat( | ||
484 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | ||
485 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | ||
486 | |||
487 | |||
435 | if (group.GetSittingAvatarsCount() != 0) | 488 | if (group.GetSittingAvatarsCount() != 0) |
436 | { | 489 | { |
437 | if (DebugLevel > 0) | 490 | if (DebugLevel > 0) |
@@ -442,7 +495,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
442 | return false; | 495 | return false; |
443 | } | 496 | } |
444 | 497 | ||
498 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
499 | if (attachments.Contains(group)) | ||
500 | { | ||
501 | // if (DebugLevel > 0) | ||
502 | // m_log.WarnFormat( | ||
503 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
504 | // group.Name, group.LocalId, sp.Name, attachmentPt); | ||
505 | |||
506 | return false; | ||
507 | } | ||
508 | |||
445 | Vector3 attachPos = group.AbsolutePosition; | 509 | Vector3 attachPos = group.AbsolutePosition; |
510 | |||
511 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | ||
512 | // be removed when that functionality is implemented in opensim | ||
513 | attachmentPt &= 0x7f; | ||
514 | |||
446 | // If the attachment point isn't the same as the one previously used | 515 | // If the attachment point isn't the same as the one previously used |
447 | // set it's offset position = 0 so that it appears on the attachment point | 516 | // set it's offset position = 0 so that it appears on the attachment point |
448 | // and not in a weird location somewhere unknown. | 517 | // and not in a weird location somewhere unknown. |
@@ -470,7 +539,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
470 | { | 539 | { |
471 | attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; | 540 | attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; |
472 | attachPos = group.RootPart.AttachedPos; | 541 | attachPos = group.RootPart.AttachedPos; |
473 | group.HasGroupChanged = true; | ||
474 | } | 542 | } |
475 | 543 | ||
476 | // if we still didn't find a suitable attachment point....... | 544 | // if we still didn't find a suitable attachment point....... |
@@ -481,21 +549,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
481 | attachPos = Vector3.Zero; | 549 | attachPos = Vector3.Zero; |
482 | } | 550 | } |
483 | 551 | ||
484 | group.AttachmentPoint = attachmentPt; | ||
485 | group.AbsolutePosition = attachPos; | ||
486 | |||
487 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
488 | |||
489 | if (attachments.Contains(group)) | ||
490 | { | ||
491 | if (DebugLevel > 0) | ||
492 | m_log.WarnFormat( | ||
493 | "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
494 | group.Name, group.LocalId, sp.Name, attachmentPt); | ||
495 | |||
496 | return false; | ||
497 | } | ||
498 | |||
499 | // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones | 552 | // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones |
500 | while (attachments.Count >= 5) | 553 | while (attachments.Count >= 5) |
501 | { | 554 | { |
@@ -514,11 +567,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
514 | } | 567 | } |
515 | } | 568 | } |
516 | 569 | ||
570 | group.DetachFromBackup(); | ||
571 | |||
517 | lock (sp.AttachmentsSyncLock) | 572 | lock (sp.AttachmentsSyncLock) |
518 | { | 573 | { |
574 | group.AttachmentPoint = attachmentPt; | ||
575 | group.RootPart.AttachedPos = attachPos; | ||
576 | |||
519 | if (addToInventory && sp.PresenceType != PresenceType.Npc) | 577 | if (addToInventory && sp.PresenceType != PresenceType.Npc) |
520 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); | 578 | UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); |
521 | 579 | ||
522 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | 580 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); |
523 | 581 | ||
524 | if (resumeScripts) | 582 | if (resumeScripts) |
@@ -529,8 +587,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
529 | group.ResumeScripts(); | 587 | group.ResumeScripts(); |
530 | } | 588 | } |
531 | 589 | ||
590 | else | ||
532 | // Do this last so that event listeners have access to all the effects of the attachment | 591 | // Do this last so that event listeners have access to all the effects of the attachment |
533 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | 592 | // this can't be done when creating scripts: |
593 | // scripts do internal enqueue of attach event | ||
594 | // and not all scripts are loaded at this point | ||
595 | m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); | ||
534 | } | 596 | } |
535 | 597 | ||
536 | return true; | 598 | return true; |
@@ -546,7 +608,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
546 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); | 608 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); |
547 | } | 609 | } |
548 | 610 | ||
549 | public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) | 611 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) |
612 | { | ||
613 | return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null); | ||
614 | } | ||
615 | |||
616 | public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc) | ||
550 | { | 617 | { |
551 | if (!Enabled) | 618 | if (!Enabled) |
552 | return null; | 619 | return null; |
@@ -557,8 +624,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
557 | (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); | 624 | (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); |
558 | 625 | ||
559 | // We check the attachments in the avatar appearance here rather than the objects attached to the | 626 | // We check the attachments in the avatar appearance here rather than the objects attached to the |
560 | // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are | 627 | // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are |
561 | // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done | 628 | // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done |
562 | // because pre-outfit folder viewers (most version 1 viewers) require it. | 629 | // because pre-outfit folder viewers (most version 1 viewers) require it. |
563 | bool alreadyOn = false; | 630 | bool alreadyOn = false; |
564 | List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments(); | 631 | List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments(); |
@@ -584,7 +651,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
584 | bool append = (AttachmentPt & 0x80) != 0; | 651 | bool append = (AttachmentPt & 0x80) != 0; |
585 | AttachmentPt &= 0x7f; | 652 | AttachmentPt &= 0x7f; |
586 | 653 | ||
587 | return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); | 654 | return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc); |
588 | } | 655 | } |
589 | 656 | ||
590 | public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) | 657 | public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) |
@@ -594,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
594 | 661 | ||
595 | if (DebugLevel > 0) | 662 | if (DebugLevel > 0) |
596 | m_log.DebugFormat( | 663 | m_log.DebugFormat( |
597 | "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", | 664 | "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", |
598 | rezlist.Count, sp.Name, m_scene.Name); | 665 | rezlist.Count, sp.Name, m_scene.Name); |
599 | 666 | ||
600 | foreach (KeyValuePair<UUID, uint> rez in rezlist) | 667 | foreach (KeyValuePair<UUID, uint> rez in rezlist) |
@@ -605,7 +672,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
605 | 672 | ||
606 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) | 673 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) |
607 | { | 674 | { |
608 | DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); | 675 | Vector3 pos = new Vector3(2.5f, 0f, 0f); |
676 | pos *= ((ScenePresence)sp).Rotation; | ||
677 | pos += sp.AbsolutePosition; | ||
678 | DetachSingleAttachmentToGround(sp, soLocalId, pos, Quaternion.Identity); | ||
609 | } | 679 | } |
610 | 680 | ||
611 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) | 681 | public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) |
@@ -649,26 +719,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
649 | if (changed && m_scene.AvatarFactory != null) | 719 | if (changed && m_scene.AvatarFactory != null) |
650 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 720 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
651 | 721 | ||
722 | so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint; | ||
723 | |||
652 | sp.RemoveAttachment(so); | 724 | sp.RemoveAttachment(so); |
653 | so.FromItemID = UUID.Zero; | 725 | so.FromItemID = UUID.Zero; |
654 | 726 | ||
727 | so.AttachedAvatar = UUID.Zero; | ||
728 | so.ClearPartAttachmentData(); | ||
729 | |||
655 | SceneObjectPart rootPart = so.RootPart; | 730 | SceneObjectPart rootPart = so.RootPart; |
731 | |||
732 | rootPart.SetParentLocalId(0); | ||
656 | so.AbsolutePosition = absolutePos; | 733 | so.AbsolutePosition = absolutePos; |
657 | if (absoluteRot != Quaternion.Identity) | 734 | if (absoluteRot != Quaternion.Identity) |
658 | { | 735 | { |
659 | so.UpdateGroupRotationR(absoluteRot); | 736 | so.UpdateGroupRotationR(absoluteRot); |
660 | } | 737 | } |
661 | so.AttachedAvatar = UUID.Zero; | 738 | |
662 | rootPart.SetParentLocalId(0); | ||
663 | so.ClearPartAttachmentData(); | ||
664 | rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); | ||
665 | so.HasGroupChanged = true; | ||
666 | so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint; | ||
667 | rootPart.Rezzed = DateTime.Now; | ||
668 | rootPart.RemFlag(PrimFlags.TemporaryOnRez); | 739 | rootPart.RemFlag(PrimFlags.TemporaryOnRez); |
740 | |||
741 | so.ApplyPhysics(); | ||
742 | |||
743 | rootPart.Rezzed = DateTime.Now; | ||
669 | so.AttachToBackup(); | 744 | so.AttachToBackup(); |
670 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | 745 | m_scene.EventManager.TriggerParcelPrimCountTainted(); |
671 | rootPart.ScheduleFullUpdate(); | 746 | |
672 | rootPart.ClearUndoState(); | 747 | rootPart.ClearUndoState(); |
673 | 748 | ||
674 | List<UUID> uuids = new List<UUID>(); | 749 | List<UUID> uuids = new List<UUID>(); |
@@ -678,6 +753,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
678 | } | 753 | } |
679 | 754 | ||
680 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); | 755 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); |
756 | |||
757 | // Attach (NULL) stops scripts. We don't want that. Resume them. | ||
758 | so.ResumeScripts(); | ||
759 | so.HasGroupChanged = true; | ||
760 | so.RootPart.ScheduleFullUpdate(); | ||
761 | so.ScheduleGroupForTerseUpdate(); | ||
681 | } | 762 | } |
682 | 763 | ||
683 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) | 764 | public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) |
@@ -691,9 +772,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
691 | return; | 772 | return; |
692 | } | 773 | } |
693 | 774 | ||
775 | // If this didn't come from inventory, it also shouldn't go there | ||
776 | // on detach. It's likely a temp attachment. | ||
777 | if (so.FromItemID == UUID.Zero) | ||
778 | { | ||
779 | // Retirn value is ignored | ||
780 | PrepareScriptInstanceForSave(so, true); | ||
781 | |||
782 | lock (sp.AttachmentsSyncLock) | ||
783 | { | ||
784 | bool changed = sp.Appearance.DetachAttachment(so.FromItemID); | ||
785 | if (changed && m_scene.AvatarFactory != null) | ||
786 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | ||
787 | |||
788 | sp.RemoveAttachment(so); | ||
789 | } | ||
790 | |||
791 | m_scene.DeleteSceneObject(so, false, false); | ||
792 | so.RemoveScriptInstances(true); | ||
793 | so.Clear(); | ||
794 | |||
795 | return; | ||
796 | } | ||
797 | |||
694 | if (DebugLevel > 0) | 798 | if (DebugLevel > 0) |
695 | m_log.DebugFormat( | 799 | m_log.DebugFormat( |
696 | "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", | 800 | "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", |
697 | so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); | 801 | so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); |
698 | 802 | ||
699 | // Scripts MUST be snapshotted before the object is | 803 | // Scripts MUST be snapshotted before the object is |
@@ -716,14 +820,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
716 | UpdateDetachedObject(sp, so, scriptedState); | 820 | UpdateDetachedObject(sp, so, scriptedState); |
717 | } | 821 | } |
718 | } | 822 | } |
719 | 823 | ||
720 | public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) | 824 | public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) |
721 | { | 825 | { |
722 | if (!Enabled) | 826 | if (!Enabled) |
723 | return; | 827 | return; |
724 | 828 | ||
725 | sog.UpdateGroupPosition(pos); | 829 | sog.UpdateGroupPosition(pos); |
726 | sog.HasGroupChanged = true; | 830 | sog.HasGroupChanged = true; |
727 | } | 831 | } |
728 | 832 | ||
729 | #endregion | 833 | #endregion |
@@ -732,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
732 | 836 | ||
733 | // This is public but is not part of the IAttachmentsModule interface. | 837 | // This is public but is not part of the IAttachmentsModule interface. |
734 | // RegionCombiner module needs to poke at it to deliver client events. | 838 | // RegionCombiner module needs to poke at it to deliver client events. |
735 | // This breaks the encapsulation of the module and should get fixed somehow. | 839 | // This breaks the encapsulation of the module and should get fixed somehow. |
736 | public void SubscribeToClientEvents(IClientAPI client) | 840 | public void SubscribeToClientEvents(IClientAPI client) |
737 | { | 841 | { |
738 | client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv; | 842 | client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv; |
@@ -745,7 +849,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
745 | 849 | ||
746 | // This is public but is not part of the IAttachmentsModule interface. | 850 | // This is public but is not part of the IAttachmentsModule interface. |
747 | // RegionCombiner module needs to poke at it to deliver client events. | 851 | // RegionCombiner module needs to poke at it to deliver client events. |
748 | // This breaks the encapsulation of the module and should get fixed somehow. | 852 | // This breaks the encapsulation of the module and should get fixed somehow. |
749 | public void UnsubscribeFromClientEvents(IClientAPI client) | 853 | public void UnsubscribeFromClientEvents(IClientAPI client) |
750 | { | 854 | { |
751 | client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv; | 855 | client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv; |
@@ -791,11 +895,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
791 | 895 | ||
792 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); | 896 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); |
793 | 897 | ||
794 | InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); | 898 | InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, grp.FromItemID); |
795 | item = m_scene.InventoryService.GetItem(item); | ||
796 | 899 | ||
797 | if (item != null) | 900 | if (item != null) |
798 | { | 901 | { |
902 | // attach is rez, need to update permissions | ||
903 | item.Flags &= ~(uint)(InventoryItemFlags.ObjectSlamPerm | InventoryItemFlags.ObjectOverwriteBase | | ||
904 | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | | ||
905 | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner); | ||
906 | |||
907 | uint permsBase = (uint)(PermissionMask.Copy | PermissionMask.Transfer | | ||
908 | PermissionMask.Modify | PermissionMask.Move | | ||
909 | PermissionMask.Export | PermissionMask.FoldedMask); | ||
910 | |||
911 | permsBase &= grp.CurrentAndFoldedNextPermissions(); | ||
912 | permsBase |= (uint)PermissionMask.Move; | ||
913 | item.BasePermissions = permsBase; | ||
914 | item.CurrentPermissions = permsBase; | ||
915 | item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask | (uint)PermissionMask.Move; | ||
916 | item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask; | ||
917 | item.GroupPermissions = permsBase & grp.RootPart.GroupMask; | ||
918 | item.CurrentPermissions &= | ||
919 | ((uint)PermissionMask.Copy | | ||
920 | (uint)PermissionMask.Transfer | | ||
921 | (uint)PermissionMask.Modify | | ||
922 | (uint)PermissionMask.Move | | ||
923 | (uint)PermissionMask.Export | | ||
924 | (uint)PermissionMask.FoldedMask); // Preserve folded permissions ?? | ||
925 | |||
799 | AssetBase asset = m_scene.CreateAsset( | 926 | AssetBase asset = m_scene.CreateAsset( |
800 | grp.GetPartName(grp.LocalId), | 927 | grp.GetPartName(grp.LocalId), |
801 | grp.GetPartDescription(grp.LocalId), | 928 | grp.GetPartDescription(grp.LocalId), |
@@ -826,7 +953,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
826 | /// Attach this scene object to the given avatar. | 953 | /// Attach this scene object to the given avatar. |
827 | /// </summary> | 954 | /// </summary> |
828 | /// <remarks> | 955 | /// <remarks> |
829 | /// This isn't publicly available since attachments should always perform the corresponding inventory | 956 | /// This isn't publicly available since attachments should always perform the corresponding inventory |
830 | /// operation (to show the attach in user inventory and update the asset with positional information). | 957 | /// operation (to show the attach in user inventory and update the asset with positional information). |
831 | /// </remarks> | 958 | /// </remarks> |
832 | /// <param name="sp"></param> | 959 | /// <param name="sp"></param> |
@@ -846,16 +973,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
846 | m_scene.DeleteFromStorage(so.UUID); | 973 | m_scene.DeleteFromStorage(so.UUID); |
847 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | 974 | m_scene.EventManager.TriggerParcelPrimCountTainted(); |
848 | 975 | ||
849 | so.AttachedAvatar = sp.UUID; | ||
850 | 976 | ||
851 | if (so.RootPart.PhysActor != null) | 977 | foreach (SceneObjectPart part in so.Parts) |
852 | so.RootPart.RemoveFromPhysics(); | 978 | { |
979 | // if (part.KeyframeMotion != null) | ||
980 | // part.KeyframeMotion.Suspend(); | ||
981 | |||
982 | if (part.PhysActor != null) | ||
983 | { | ||
984 | part.RemoveFromPhysics(); | ||
985 | } | ||
986 | } | ||
853 | 987 | ||
854 | so.AbsolutePosition = attachOffset; | ||
855 | so.RootPart.AttachedPos = attachOffset; | ||
856 | so.IsAttachment = true; | ||
857 | so.RootPart.SetParentLocalId(sp.LocalId); | 988 | so.RootPart.SetParentLocalId(sp.LocalId); |
989 | so.AttachedAvatar = sp.UUID; | ||
858 | so.AttachmentPoint = attachmentpoint; | 990 | so.AttachmentPoint = attachmentpoint; |
991 | so.RootPart.AttachedPos = attachOffset; | ||
992 | so.AbsolutePosition = attachOffset; | ||
993 | so.IsAttachment = true; | ||
859 | 994 | ||
860 | sp.AddAttachment(so); | 995 | sp.AddAttachment(so); |
861 | 996 | ||
@@ -879,7 +1014,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
879 | 1014 | ||
880 | // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update | 1015 | // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update |
881 | // will succeed, as that will not update if an attachment is selected. | 1016 | // will succeed, as that will not update if an attachment is selected. |
882 | so.IsSelected = false; // fudge.... | 1017 | so.IsSelected = false; // fudge.... |
883 | 1018 | ||
884 | so.ScheduleGroupForFullUpdate(); | 1019 | so.ScheduleGroupForFullUpdate(); |
885 | } | 1020 | } |
@@ -923,7 +1058,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
923 | /// </summary> | 1058 | /// </summary> |
924 | /// <remarks> | 1059 | /// <remarks> |
925 | /// This involves triggering the detach event and getting the script state (which also stops the script) | 1060 | /// This involves triggering the detach event and getting the script state (which also stops the script) |
926 | /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a | 1061 | /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a |
927 | /// running script is performing attachment operations. | 1062 | /// running script is performing attachment operations. |
928 | /// </remarks> | 1063 | /// </remarks> |
929 | /// <returns> | 1064 | /// <returns> |
@@ -939,7 +1074,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
939 | if (fireDetachEvent) | 1074 | if (fireDetachEvent) |
940 | { | 1075 | { |
941 | m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); | 1076 | m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); |
942 | |||
943 | // Allow detach event time to do some work before stopping the script | 1077 | // Allow detach event time to do some work before stopping the script |
944 | Thread.Sleep(2); | 1078 | Thread.Sleep(2); |
945 | } | 1079 | } |
@@ -971,6 +1105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
971 | // Remove the object from the scene so no more updates | 1105 | // Remove the object from the scene so no more updates |
972 | // are sent. Doing this before the below changes will ensure | 1106 | // are sent. Doing this before the below changes will ensure |
973 | // updates can't cause "HUD artefacts" | 1107 | // updates can't cause "HUD artefacts" |
1108 | |||
974 | m_scene.DeleteSceneObject(so, false, false); | 1109 | m_scene.DeleteSceneObject(so, false, false); |
975 | 1110 | ||
976 | // Prepare sog for storage | 1111 | // Prepare sog for storage |
@@ -989,23 +1124,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
989 | 1124 | ||
990 | // Now, remove the scripts | 1125 | // Now, remove the scripts |
991 | so.RemoveScriptInstances(true); | 1126 | so.RemoveScriptInstances(true); |
1127 | so.Clear(); | ||
992 | } | 1128 | } |
993 | 1129 | ||
994 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( | 1130 | protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( |
995 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) | 1131 | IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc) |
996 | { | 1132 | { |
997 | if (m_invAccessModule == null) | 1133 | if (m_invAccessModule == null) |
998 | return null; | 1134 | return null; |
999 | 1135 | ||
1000 | SceneObjectGroup objatt; | 1136 | SceneObjectGroup objatt; |
1001 | 1137 | ||
1138 | UUID rezGroupID; | ||
1139 | |||
1140 | // This will fail if the user aborts login. sp will exist | ||
1141 | // but ControllintClient will be null. | ||
1142 | try | ||
1143 | { | ||
1144 | rezGroupID = sp.ControllingClient.ActiveGroupId; | ||
1145 | } | ||
1146 | catch | ||
1147 | { | ||
1148 | return null; | ||
1149 | } | ||
1150 | |||
1002 | if (itemID != UUID.Zero) | 1151 | if (itemID != UUID.Zero) |
1003 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | 1152 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, |
1004 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | 1153 | itemID, rezGroupID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, |
1005 | false, false, sp.UUID, true); | 1154 | false, false, sp.UUID, true); |
1006 | else | 1155 | else |
1007 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, | 1156 | objatt = m_invAccessModule.RezObject(sp.ControllingClient, |
1008 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | 1157 | null, rezGroupID, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, |
1009 | false, false, sp.UUID, true); | 1158 | false, false, sp.UUID, true); |
1010 | 1159 | ||
1011 | if (objatt == null) | 1160 | if (objatt == null) |
@@ -1018,7 +1167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1018 | } | 1167 | } |
1019 | else if (itemID == UUID.Zero) | 1168 | else if (itemID == UUID.Zero) |
1020 | { | 1169 | { |
1021 | // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is | 1170 | // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is |
1022 | // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory | 1171 | // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory |
1023 | // we will satisfy this requirement by inserting a random UUID. | 1172 | // we will satisfy this requirement by inserting a random UUID. |
1024 | objatt.FromItemID = UUID.Random(); | 1173 | objatt.FromItemID = UUID.Random(); |
@@ -1043,6 +1192,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1043 | // This will throw if the attachment fails | 1192 | // This will throw if the attachment fails |
1044 | try | 1193 | try |
1045 | { | 1194 | { |
1195 | if (doc != null) | ||
1196 | { | ||
1197 | objatt.LoadScriptState(doc); | ||
1198 | objatt.ResetOwnerChangeFlag(); | ||
1199 | } | ||
1200 | |||
1046 | AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); | 1201 | AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); |
1047 | } | 1202 | } |
1048 | catch (Exception e) | 1203 | catch (Exception e) |
@@ -1058,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1058 | } | 1213 | } |
1059 | 1214 | ||
1060 | if (tainted) | 1215 | if (tainted) |
1061 | objatt.HasGroupChanged = true; | 1216 | objatt.HasGroupChanged = true; |
1062 | 1217 | ||
1063 | if (ThrottlePer100PrimsRezzed > 0) | 1218 | if (ThrottlePer100PrimsRezzed > 0) |
1064 | { | 1219 | { |
@@ -1100,8 +1255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1100 | return; | 1255 | return; |
1101 | } | 1256 | } |
1102 | 1257 | ||
1103 | InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); | 1258 | InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, itemID); |
1104 | item = m_scene.InventoryService.GetItem(item); | ||
1105 | if (item == null) | 1259 | if (item == null) |
1106 | return; | 1260 | return; |
1107 | 1261 | ||
@@ -1185,7 +1339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1185 | if (part == null) | 1339 | if (part == null) |
1186 | return; | 1340 | return; |
1187 | 1341 | ||
1188 | if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) | 1342 | SceneObjectGroup group = part.ParentGroup; |
1343 | |||
1344 | if (!m_scene.Permissions.CanTakeObject(group, sp)) | ||
1189 | { | 1345 | { |
1190 | remoteClient.SendAgentAlertMessage( | 1346 | remoteClient.SendAgentAlertMessage( |
1191 | "You don't have sufficient permissions to attach this object", false); | 1347 | "You don't have sufficient permissions to attach this object", false); |
@@ -1197,7 +1353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1197 | AttachmentPt &= 0x7f; | 1353 | AttachmentPt &= 0x7f; |
1198 | 1354 | ||
1199 | // Calls attach with a Zero position | 1355 | // Calls attach with a Zero position |
1200 | if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) | 1356 | if (AttachObject(sp, group , AttachmentPt, false, true, append)) |
1201 | { | 1357 | { |
1202 | if (DebugLevel > 0) | 1358 | if (DebugLevel > 0) |
1203 | m_log.Debug( | 1359 | m_log.Debug( |
@@ -1205,7 +1361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1205 | + ", AttachmentPoint: " + AttachmentPt); | 1361 | + ", AttachmentPoint: " + AttachmentPt); |
1206 | 1362 | ||
1207 | // Save avatar attachment information | 1363 | // Save avatar attachment information |
1208 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); | 1364 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
1209 | } | 1365 | } |
1210 | } | 1366 | } |
1211 | catch (Exception e) | 1367 | catch (Exception e) |
@@ -1222,7 +1378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1222 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 1378 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
1223 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); | 1379 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); |
1224 | 1380 | ||
1225 | if (sp != null && group != null && group.FromItemID != UUID.Zero) | 1381 | if (sp != null && group != null) |
1226 | DetachSingleAttachmentToInv(sp, group); | 1382 | DetachSingleAttachmentToInv(sp, group); |
1227 | } | 1383 | } |
1228 | 1384 | ||
@@ -1256,7 +1412,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1256 | if (sp != null) | 1412 | if (sp != null) |
1257 | DetachSingleAttachmentToGround(sp, soLocalId); | 1413 | DetachSingleAttachmentToGround(sp, soLocalId); |
1258 | } | 1414 | } |
1259 | |||
1260 | #endregion | 1415 | #endregion |
1261 | } | 1416 | } |
1262 | } | 1417 | } |