diff options
Bring us up to date.
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 494 |
1 files changed, 266 insertions, 228 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 218b7b8..2bf418d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -144,20 +144,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
144 | 144 | ||
145 | public void SaveChangedAttachments(IScenePresence sp) | 145 | public void SaveChangedAttachments(IScenePresence sp) |
146 | { | 146 | { |
147 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); | ||
148 | |||
147 | foreach (SceneObjectGroup grp in sp.GetAttachments()) | 149 | foreach (SceneObjectGroup grp in sp.GetAttachments()) |
148 | { | 150 | { |
149 | if (grp.HasGroupChanged) // Resizer scripts? | 151 | // if (grp.HasGroupChanged) // Resizer scripts? |
150 | { | 152 | // { |
151 | grp.IsAttachment = false; | 153 | grp.IsAttachment = false; |
152 | grp.AbsolutePosition = grp.RootPart.AttachedPos; | 154 | grp.AbsolutePosition = grp.RootPart.AttachedPos; |
153 | UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); | 155 | UpdateKnownItem(sp.ControllingClient, grp); |
154 | grp.IsAttachment = true; | 156 | grp.IsAttachment = true; |
155 | } | 157 | // } |
156 | } | 158 | } |
157 | } | 159 | } |
158 | 160 | ||
159 | public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) | 161 | public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) |
160 | { | 162 | { |
163 | // m_log.DebugFormat( | ||
164 | // "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", | ||
165 | // m_scene.RegionInfo.RegionName, sp.Name, silent); | ||
166 | |||
161 | foreach (SceneObjectGroup sop in sp.GetAttachments()) | 167 | foreach (SceneObjectGroup sop in sp.GetAttachments()) |
162 | { | 168 | { |
163 | sop.Scene.DeleteSceneObject(sop, silent); | 169 | sop.Scene.DeleteSceneObject(sop, silent); |
@@ -220,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
220 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); | 226 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); |
221 | 227 | ||
222 | // Save avatar attachment information | 228 | // Save avatar attachment information |
223 | m_log.Info( | 229 | m_log.Debug( |
224 | "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId | 230 | "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId |
225 | + ", AttachmentPoint: " + AttachmentPt); | 231 | + ", AttachmentPoint: " + AttachmentPt); |
226 | 232 | ||
@@ -248,75 +254,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
248 | 254 | ||
249 | private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) | 255 | private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) |
250 | { | 256 | { |
251 | // m_log.DebugFormat( | 257 | lock (sp.AttachmentsSyncLock) |
252 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | ||
253 | // group.Name, group.LocalId, sp.Name, AttachmentPt, silent); | ||
254 | |||
255 | if (sp.GetAttachments(attachmentPt).Contains(group)) | ||
256 | { | ||
257 | // m_log.WarnFormat( | ||
258 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
259 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | ||
260 | |||
261 | return false; | ||
262 | } | ||
263 | |||
264 | Vector3 attachPos = group.AbsolutePosition; | ||
265 | |||
266 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | ||
267 | // be removed when that functionality is implemented in opensim | ||
268 | attachmentPt &= 0x7f; | ||
269 | |||
270 | // If the attachment point isn't the same as the one previously used | ||
271 | // set it's offset position = 0 so that it appears on the attachment point | ||
272 | // and not in a weird location somewhere unknown. | ||
273 | if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) | ||
274 | { | ||
275 | attachPos = Vector3.Zero; | ||
276 | } | ||
277 | |||
278 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
279 | if (attachmentPt == 0) | ||
280 | { | 258 | { |
281 | // Check object for stored attachment point | 259 | // m_log.DebugFormat( |
282 | attachmentPt = group.AttachmentPoint; | 260 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", |
283 | } | 261 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); |
284 | 262 | ||
285 | // if we still didn't find a suitable attachment point....... | 263 | if (sp.GetAttachments(attachmentPt).Contains(group)) |
286 | if (attachmentPt == 0) | 264 | { |
287 | { | 265 | // m_log.WarnFormat( |
288 | // Stick it on left hand with Zero Offset from the attachment point. | 266 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", |
289 | attachmentPt = (uint)AttachmentPoint.LeftHand; | 267 | // group.Name, group.LocalId, sp.Name, AttachmentPt); |
290 | attachPos = Vector3.Zero; | 268 | |
291 | } | 269 | return false; |
292 | 270 | } | |
293 | group.AttachmentPoint = attachmentPt; | 271 | |
294 | group.AbsolutePosition = attachPos; | 272 | Vector3 attachPos = group.AbsolutePosition; |
295 | 273 | ||
296 | // Remove any previous attachments | 274 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should |
297 | UUID itemID = UUID.Zero; | 275 | // be removed when that functionality is implemented in opensim |
298 | 276 | attachmentPt &= 0x7f; | |
299 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | 277 | |
300 | 278 | // If the attachment point isn't the same as the one previously used | |
301 | // At the moment we can only deal with a single attachment | 279 | // set it's offset position = 0 so that it appears on the attachment point |
302 | // We also don't want to do any of the inventory operations for an NPC. | 280 | // and not in a weird location somewhere unknown. |
303 | if (sp.PresenceType != PresenceType.Npc) | 281 | if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) |
304 | { | 282 | { |
305 | if (attachments.Count != 0) | 283 | attachPos = Vector3.Zero; |
306 | itemID = attachments[0].GetFromItemID(); | 284 | } |
285 | |||
286 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
287 | if (attachmentPt == 0) | ||
288 | { | ||
289 | // Check object for stored attachment point | ||
290 | attachmentPt = group.AttachmentPoint; | ||
291 | } | ||
292 | |||
293 | // if we still didn't find a suitable attachment point....... | ||
294 | if (attachmentPt == 0) | ||
295 | { | ||
296 | // Stick it on left hand with Zero Offset from the attachment point. | ||
297 | attachmentPt = (uint)AttachmentPoint.LeftHand; | ||
298 | attachPos = Vector3.Zero; | ||
299 | } | ||
300 | |||
301 | group.AttachmentPoint = attachmentPt; | ||
302 | group.AbsolutePosition = attachPos; | ||
303 | |||
304 | // We also don't want to do any of the inventory operations for an NPC. | ||
305 | if (sp.PresenceType != PresenceType.Npc) | ||
306 | { | ||
307 | // Remove any previous attachments | ||
308 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
307 | 309 | ||
308 | if (itemID != UUID.Zero) | 310 | // At the moment we can only deal with a single attachment |
309 | DetachSingleAttachmentToInv(itemID, sp); | 311 | if (attachments.Count != 0) |
312 | { | ||
313 | UUID oldAttachmentItemID = attachments[0].GetFromItemID(); | ||
314 | |||
315 | if (oldAttachmentItemID != UUID.Zero) | ||
316 | DetachSingleAttachmentToInv(oldAttachmentItemID, sp); | ||
317 | else | ||
318 | 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!", | ||
320 | attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
321 | } | ||
310 | 322 | ||
311 | itemID = group.GetFromItemID(); | 323 | // Add the new attachment to inventory if we don't already have it. |
312 | if (itemID == UUID.Zero) | 324 | UUID newAttachmentItemID = group.GetFromItemID(); |
313 | itemID = AddSceneObjectAsAttachment(sp.ControllingClient, group).ID; | 325 | if (newAttachmentItemID == UUID.Zero) |
326 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; | ||
327 | |||
328 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | ||
329 | } | ||
314 | 330 | ||
315 | ShowAttachInUserInventory(sp, attachmentPt, itemID, group); | 331 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); |
316 | } | 332 | } |
317 | 333 | ||
318 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | ||
319 | |||
320 | return true; | 334 | return true; |
321 | } | 335 | } |
322 | 336 | ||
@@ -325,20 +339,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
325 | RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, | 339 | RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, |
326 | RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) | 340 | RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) |
327 | { | 341 | { |
328 | foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) | 342 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
343 | |||
344 | if (sp == null) | ||
329 | { | 345 | { |
330 | RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); | 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 | } | ||
331 | } | 360 | } |
332 | } | 361 | } |
333 | 362 | ||
334 | public ISceneEntity RezSingleAttachmentFromInventory( | 363 | public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) |
335 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt) | ||
336 | { | ||
337 | return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true); | ||
338 | } | ||
339 | |||
340 | public ISceneEntity RezSingleAttachmentFromInventory( | ||
341 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus) | ||
342 | { | 364 | { |
343 | return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null); | 365 | return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null); |
344 | } | 366 | } |
@@ -347,21 +369,59 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
347 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) | 369 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) |
348 | { | 370 | { |
349 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 371 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
350 | if (sp == null) { m_log.ErrorFormat( "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()", remoteClient.Name, remoteClient.AgentId); return null; } | 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; | ||
379 | } | ||
380 | |||
381 | return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt); | ||
382 | } | ||
383 | |||
384 | public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt) | ||
385 | { | ||
386 | // m_log.DebugFormat( | ||
387 | // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", | ||
388 | // (AttachmentPoint)AttachmentPt, itemID, sp.Name); | ||
389 | |||
351 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | 390 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should |
352 | // be removed when that functionality is implemented in opensim | 391 | // be removed when that functionality is implemented in opensim |
353 | AttachmentPt &= 0x7f; | 392 | AttachmentPt &= 0x7f; |
354 | 393 | ||
355 | SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); | 394 | // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). |
395 | // This often happens during login - not sure the exact reason. | ||
396 | // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the | ||
397 | // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login | ||
398 | // before anything has actually been attached. | ||
399 | bool alreadyOn = false; | ||
400 | List<SceneObjectGroup> existingAttachments = sp.GetAttachments(); | ||
401 | foreach (SceneObjectGroup so in existingAttachments) | ||
402 | { | ||
403 | if (so.GetFromItemID() == itemID) | ||
404 | { | ||
405 | alreadyOn = true; | ||
406 | break; | ||
407 | } | ||
408 | } | ||
356 | 409 | ||
357 | if (updateInventoryStatus) | 410 | // if (sp.Appearance.GetAttachmentForItem(itemID) != null) |
411 | if (alreadyOn) | ||
358 | { | 412 | { |
359 | if (att == null) | 413 | // m_log.WarnFormat( |
360 | DetachSingleAttachmentToInv(itemID, sp.ControllingClient); | 414 | // "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", |
361 | else | 415 | // sp.Name, itemID, AttachmentPt); |
362 | ShowAttachInUserInventory(att, sp, itemID, AttachmentPt); | 416 | |
417 | return null; | ||
363 | } | 418 | } |
364 | 419 | ||
420 | SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, null); | ||
421 | |||
422 | if (att == null) | ||
423 | DetachSingleAttachmentToInv(itemID, sp.ControllingClient); | ||
424 | |||
365 | return att; | 425 | return att; |
366 | } | 426 | } |
367 | 427 | ||
@@ -371,50 +431,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
371 | IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); | 431 | IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); |
372 | if (invAccess != null) | 432 | if (invAccess != null) |
373 | { | 433 | { |
374 | SceneObjectGroup objatt; | 434 | lock (sp.AttachmentsSyncLock) |
375 | |||
376 | if (itemID != UUID.Zero) | ||
377 | objatt = invAccess.RezObject(sp.ControllingClient, | ||
378 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
379 | false, false, sp.UUID, true); | ||
380 | else | ||
381 | objatt = invAccess.RezObject(sp.ControllingClient, | ||
382 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
383 | false, false, sp.UUID, true); | ||
384 | |||
385 | // m_log.DebugFormat( | ||
386 | // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", | ||
387 | // objatt.Name, remoteClient.Name, AttachmentPt); | ||
388 | |||
389 | if (objatt != null) | ||
390 | { | 435 | { |
391 | // Loading the inventory from XML will have set this, but | 436 | SceneObjectGroup objatt; |
392 | // there is no way the object could have changed yet, | 437 | |
393 | // since scripts aren't running yet. So, clear it here. | 438 | if (itemID != UUID.Zero) |
394 | objatt.HasGroupChanged = false; | 439 | objatt = invAccess.RezObject(sp.ControllingClient, |
395 | bool tainted = false; | 440 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, |
396 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | 441 | false, false, sp.UUID, true); |
397 | tainted = true; | 442 | else |
398 | 443 | objatt = invAccess.RezObject(sp.ControllingClient, | |
399 | // This will throw if the attachment fails | 444 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, |
400 | try | 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) | ||
401 | { | 452 | { |
402 | AttachObject(sp, objatt, attachmentPt, false); | 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; | ||
403 | } | 488 | } |
404 | catch (Exception e) | 489 | else |
405 | { | 490 | { |
406 | m_log.ErrorFormat( | 491 | m_log.WarnFormat( |
407 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | 492 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", |
408 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | 493 | itemID, sp.Name, attachmentPt); |
409 | |||
410 | // Make sure the object doesn't stick around and bail | ||
411 | sp.RemoveAttachment(objatt); | ||
412 | m_scene.DeleteSceneObject(objatt, false); | ||
413 | return null; | ||
414 | } | 494 | } |
415 | |||
416 | if (tainted) | ||
417 | objatt.HasGroupChanged = true; | ||
418 | 495 | ||
419 | if (doc != null) | 496 | if (doc != null) |
420 | { | 497 | { |
@@ -430,47 +507,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
430 | // Do this last so that event listeners have access to all the effects of the attachment | 507 | // Do this last so that event listeners have access to all the effects of the attachment |
431 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | 508 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); |
432 | } | 509 | } |
433 | else | ||
434 | { | ||
435 | m_log.WarnFormat( | ||
436 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
437 | itemID, sp.Name, attachmentPt); | ||
438 | } | ||
439 | |||
440 | return objatt; | ||
441 | } | 510 | } |
442 | 511 | ||
443 | return null; | 512 | return null; |
444 | } | 513 | } |
445 | |||
446 | /// <summary> | ||
447 | /// Update the user inventory to the attachment of an item | ||
448 | /// </summary> | ||
449 | /// <param name="att"></param> | ||
450 | /// <param name="sp"></param> | ||
451 | /// <param name="itemID"></param> | ||
452 | /// <param name="attachmentPoint"></param> | ||
453 | /// <returns></returns> | ||
454 | private UUID ShowAttachInUserInventory( | ||
455 | SceneObjectGroup att, IScenePresence sp, UUID itemID, uint attachmentPoint) | ||
456 | { | ||
457 | // m_log.DebugFormat( | ||
458 | // "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} {2} (item ID {3}) at {4}", | ||
459 | // sp.Name, att.Name, att.LocalId, itemID, AttachmentPt); | ||
460 | |||
461 | if (!att.IsDeleted) | ||
462 | attachmentPoint = att.AttachmentPoint; | ||
463 | |||
464 | InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); | ||
465 | if (m_scene.InventoryService != null) | ||
466 | item = m_scene.InventoryService.GetItem(item); | ||
467 | |||
468 | bool changed = sp.Appearance.SetAttachment((int)attachmentPoint, itemID, item.AssetID); | ||
469 | if (changed && m_scene.AvatarFactory != null) | ||
470 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | ||
471 | |||
472 | return att.UUID; | ||
473 | } | ||
474 | 514 | ||
475 | /// <summary> | 515 | /// <summary> |
476 | /// Update the user inventory to reflect an attachment | 516 | /// Update the user inventory to reflect an attachment |
@@ -483,8 +523,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
483 | IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) | 523 | IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) |
484 | { | 524 | { |
485 | // m_log.DebugFormat( | 525 | // m_log.DebugFormat( |
486 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", | 526 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", |
487 | // att.Name, remoteClient.Name, AttachmentPt, itemID); | 527 | // att.Name, sp.Name, AttachmentPt, itemID); |
488 | 528 | ||
489 | if (UUID.Zero == itemID) | 529 | if (UUID.Zero == itemID) |
490 | { | 530 | { |
@@ -518,6 +558,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
518 | 558 | ||
519 | public void DetachObject(uint objectLocalID, IClientAPI remoteClient) | 559 | public void DetachObject(uint objectLocalID, IClientAPI remoteClient) |
520 | { | 560 | { |
561 | // m_log.DebugFormat( | ||
562 | // "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name); | ||
563 | |||
521 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); | 564 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); |
522 | if (group != null) | 565 | if (group != null) |
523 | { | 566 | { |
@@ -530,14 +573,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
530 | ScenePresence presence; | 573 | ScenePresence presence; |
531 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) | 574 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) |
532 | { | 575 | { |
533 | // Save avatar attachment information | 576 | lock (presence.AttachmentsSyncLock) |
534 | m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); | 577 | { |
535 | 578 | // Save avatar attachment information | |
536 | bool changed = presence.Appearance.DetachAttachment(itemID); | 579 | m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); |
537 | if (changed && m_scene.AvatarFactory != null) | ||
538 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); | ||
539 | 580 | ||
540 | DetachSingleAttachmentToInv(itemID, presence); | 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 | } | ||
541 | } | 587 | } |
542 | } | 588 | } |
543 | 589 | ||
@@ -545,7 +591,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
545 | { | 591 | { |
546 | // m_log.DebugFormat( | 592 | // m_log.DebugFormat( |
547 | // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", | 593 | // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", |
548 | // remoteClient.Name, sceneObjectID); | 594 | // remoteClient.Name, soLocalId); |
549 | 595 | ||
550 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); | 596 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); |
551 | 597 | ||
@@ -564,24 +610,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
564 | ScenePresence presence; | 610 | ScenePresence presence; |
565 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) | 611 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) |
566 | { | 612 | { |
567 | if (!m_scene.Permissions.CanRezObject( | 613 | lock (presence.AttachmentsSyncLock) |
568 | so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) | 614 | { |
569 | return; | 615 | if (!m_scene.Permissions.CanRezObject( |
616 | so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) | ||
617 | return; | ||
570 | 618 | ||
571 | bool changed = presence.Appearance.DetachAttachment(inventoryID); | 619 | bool changed = presence.Appearance.DetachAttachment(inventoryID); |
572 | if (changed && m_scene.AvatarFactory != null) | 620 | if (changed && m_scene.AvatarFactory != null) |
573 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); | 621 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); |
574 | 622 | ||
575 | presence.RemoveAttachment(so); | 623 | presence.RemoveAttachment(so); |
576 | DetachSceneObjectToGround(so, presence); | 624 | DetachSceneObjectToGround(so, presence); |
577 | 625 | ||
578 | List<UUID> uuids = new List<UUID>(); | 626 | List<UUID> uuids = new List<UUID>(); |
579 | uuids.Add(inventoryID); | 627 | uuids.Add(inventoryID); |
580 | m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); | 628 | m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); |
581 | remoteClient.SendRemoveInventoryItem(inventoryID); | 629 | remoteClient.SendRemoveInventoryItem(inventoryID); |
582 | } | 630 | } |
583 | 631 | ||
584 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); | 632 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); |
633 | } | ||
585 | } | 634 | } |
586 | 635 | ||
587 | /// <summary> | 636 | /// <summary> |
@@ -615,6 +664,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
615 | // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? | 664 | // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? |
616 | private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) | 665 | private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) |
617 | { | 666 | { |
667 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
668 | |||
618 | if (itemID == UUID.Zero) // If this happened, someone made a mistake.... | 669 | if (itemID == UUID.Zero) // If this happened, someone made a mistake.... |
619 | return; | 670 | return; |
620 | 671 | ||
@@ -623,40 +674,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
623 | EntityBase[] detachEntities = m_scene.GetEntities(); | 674 | EntityBase[] detachEntities = m_scene.GetEntities(); |
624 | SceneObjectGroup group; | 675 | SceneObjectGroup group; |
625 | 676 | ||
626 | foreach (EntityBase entity in detachEntities) | 677 | lock (sp.AttachmentsSyncLock) |
627 | { | 678 | { |
628 | if (entity is SceneObjectGroup) | 679 | foreach (EntityBase entity in detachEntities) |
629 | { | 680 | { |
630 | group = (SceneObjectGroup)entity; | 681 | if (entity is SceneObjectGroup) |
631 | if (group.GetFromItemID() == itemID) | ||
632 | { | 682 | { |
633 | m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); | 683 | group = (SceneObjectGroup)entity; if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); |
634 | // CM / XMREngine!!!! Needed to conclude attach event | 684 | // CM / XMREngine!!!! Needed to conclude attach event |
635 | //SceneObjectSerializer.ToOriginalXmlFormat(group); | 685 | //SceneObjectSerializer.ToOriginalXmlFormat(group); |
636 | group.DetachToInventoryPrep(); | 686 | group.DetachToInventoryPrep(); |
637 | m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); | 687 | m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); |
638 | 688 | ||
639 | // Prepare sog for storage | 689 | // Prepare sog for storage |
640 | group.AttachedAvatar = UUID.Zero; | 690 | group.AttachedAvatar = UUID.Zero; |
641 | 691 | group.RootPart.SetParentLocalId(0); | |
642 | group.ForEachPart( | 692 | group.IsAttachment = false; |
643 | delegate(SceneObjectPart part) | 693 | group.AbsolutePosition = group.RootPart.AttachedPos; |
644 | { | ||
645 | // If there are any scripts, | ||
646 | // then always trigger a new object and state persistence in UpdateKnownItem() | ||
647 | if (part.Inventory.ContainsScripts()) | ||
648 | group.HasGroupChanged = true; | ||
649 | } | ||
650 | ); | ||
651 | |||
652 | group.RootPart.SetParentLocalId(0); | ||
653 | group.IsAttachment = false; | ||
654 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
655 | 694 | ||
656 | UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); | 695 | UpdateKnownItem(sp.ControllingClient, group); |
657 | m_scene.DeleteSceneObject(group, false); | 696 | m_scene.DeleteSceneObject(group, false); |
658 | 697 | ||
659 | return; | 698 | return; |
699 | } | ||
660 | } | 700 | } |
661 | } | 701 | } |
662 | } | 702 | } |
@@ -687,28 +727,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
687 | /// </remarks> | 727 | /// </remarks> |
688 | /// <param name="remoteClient"></param> | 728 | /// <param name="remoteClient"></param> |
689 | /// <param name="grp"></param> | 729 | /// <param name="grp"></param> |
690 | /// <param name="itemID"></param> | 730 | private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp) |
691 | /// <param name="agentID"></param> | ||
692 | public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) | ||
693 | { | 731 | { |
694 | if (grp != null) | 732 | if (grp.HasGroupChanged || grp.ContainsScripts()) |
695 | { | 733 | { |
696 | if (!grp.HasGroupChanged) | ||
697 | { | ||
698 | m_log.DebugFormat( | ||
699 | "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", | ||
700 | grp.UUID, grp.AttachmentPoint); | ||
701 | |||
702 | return; | ||
703 | } | ||
704 | |||
705 | m_log.DebugFormat( | 734 | m_log.DebugFormat( |
706 | "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", | 735 | "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", |
707 | grp.UUID, grp.AttachmentPoint); | 736 | grp.UUID, grp.AttachmentPoint); |
708 | 737 | ||
709 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); | 738 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); |
710 | 739 | ||
711 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); | 740 | InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId); |
712 | item = m_scene.InventoryService.GetItem(item); | 741 | item = m_scene.InventoryService.GetItem(item); |
713 | 742 | ||
714 | if (item != null) | 743 | if (item != null) |
@@ -734,6 +763,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
734 | remoteClient.SendInventoryItemCreateUpdate(item, 0); | 763 | remoteClient.SendInventoryItemCreateUpdate(item, 0); |
735 | } | 764 | } |
736 | } | 765 | } |
766 | else | ||
767 | { | ||
768 | m_log.DebugFormat( | ||
769 | "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", | ||
770 | grp.UUID, grp.AttachmentPoint); | ||
771 | } | ||
737 | } | 772 | } |
738 | 773 | ||
739 | /// <summary> | 774 | /// <summary> |
@@ -751,7 +786,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
751 | private void AttachToAgent( | 786 | private void AttachToAgent( |
752 | IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) | 787 | IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) |
753 | { | 788 | { |
754 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", | 789 | // m_log.DebugFormat( |
790 | // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", | ||
755 | // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); | 791 | // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); |
756 | 792 | ||
757 | so.DetachFromBackup(); | 793 | so.DetachFromBackup(); |
@@ -788,14 +824,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
788 | } | 824 | } |
789 | 825 | ||
790 | /// <summary> | 826 | /// <summary> |
791 | /// Add a scene object that was previously free in the scene as an attachment to an avatar. | 827 | /// Add a scene object as a new attachment in the user inventory. |
792 | /// </summary> | 828 | /// </summary> |
793 | /// <param name="remoteClient"></param> | 829 | /// <param name="remoteClient"></param> |
794 | /// <param name="grp"></param> | 830 | /// <param name="grp"></param> |
795 | /// <returns>The user inventory item created that holds the attachment.</returns> | 831 | /// <returns>The user inventory item created that holds the attachment.</returns> |
796 | private InventoryItemBase AddSceneObjectAsAttachment(IClientAPI remoteClient, SceneObjectGroup grp) | 832 | private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) |
797 | { | 833 | { |
798 | // m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); | 834 | // m_log.DebugFormat( |
835 | // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", | ||
836 | // grp.Name, grp.LocalId, remoteClient.Name); | ||
799 | 837 | ||
800 | Vector3 inventoryStoredPosition = new Vector3 | 838 | Vector3 inventoryStoredPosition = new Vector3 |
801 | (((grp.AbsolutePosition.X > (int)Constants.RegionSize) | 839 | (((grp.AbsolutePosition.X > (int)Constants.RegionSize) |
@@ -879,4 +917,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
879 | return item; | 917 | return item; |
880 | } | 918 | } |
881 | } | 919 | } |
882 | } | 920 | } \ No newline at end of file |