aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs231
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs263
2 files changed, 351 insertions, 143 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a0a7a68..296f198 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -304,21 +304,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
304 if (!Enabled) 304 if (!Enabled)
305 return false; 305 return false;
306 306
307 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, append)) 307 AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, append);
308 {
309 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
310 return true;
311 }
312
313 return false;
314 } 308 }
315 309
310 /// <summary>
311 /// Internal method which actually does all the work for attaching an object.
312 /// </summary>
313 /// <returns>The object attached.</returns>
314 /// <param name='sp'></param>
315 /// <param name='group'>The object to attach.</param>
316 /// <param name='attachmentPt'></param>
317 /// <param name='silent'></param>
318 /// <param name='temp'></param>
319 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
316 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append) 320 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
317 { 321 {
318// m_log.DebugFormat( 322// m_log.DebugFormat(
319// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 323// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
320// group.Name, group.LocalId, sp.Name, attachmentPt, silent); 324// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
321 325
326 if (sp.GetAttachments().Contains(group))
327 {
328// m_log.WarnFormat(
329// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
330// group.Name, group.LocalId, sp.Name, AttachmentPt);
331
332 return false;
333 }
334
322 if (group.GetSittingAvatarsCount() != 0) 335 if (group.GetSittingAvatarsCount() != 0)
323 { 336 {
324// m_log.WarnFormat( 337// m_log.WarnFormat(
@@ -328,67 +341,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
328 return false; 341 return false;
329 } 342 }
330 343
331 if (sp.GetAttachments(attachmentPt).Contains(group)) 344 Vector3 attachPos = group.AbsolutePosition;
345
346 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
347 // be removed when that functionality is implemented in opensim
348 attachmentPt &= 0x7f;
349
350 // If the attachment point isn't the same as the one previously used
351 // set it's offset position = 0 so that it appears on the attachment point
352 // and not in a weird location somewhere unknown.
353 if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint)
332 { 354 {
333// m_log.WarnFormat( 355 attachPos = Vector3.Zero;
334// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", 356 }
335// group.Name, group.LocalId, sp.Name, AttachmentPt);
336 357
337 return false; 358 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment.
359 if (attachmentPt == (uint)AttachmentPoint.Default)
360 {
361 // Check object for stored attachment point
362 attachmentPt = group.AttachmentPoint;
338 } 363 }
339 364
340 // Remove any previous attachments 365 // if we still didn't find a suitable attachment point.......
341 List<SceneObjectGroup> existingAttachments = sp.GetAttachments(attachmentPt); 366 if (attachmentPt == 0)
367 {
368 // Stick it on left hand with Zero Offset from the attachment point.
369 attachmentPt = (uint)AttachmentPoint.LeftHand;
370 attachPos = Vector3.Zero;
371 }
342 372
343 // At the moment we can only deal with a single attachment 373 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
344 if (existingAttachments.Count != 0 && existingAttachments[0].FromItemID != UUID.Zero)
345 DetachSingleAttachmentToInv(sp, group);
346 374
347 lock (sp.AttachmentsSyncLock) 375 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
376 while (attachments.Count >= 5)
348 { 377 {
349 Vector3 attachPos = group.AbsolutePosition; 378 if (attachments[0].FromItemID != UUID.Zero)
350 379 DetachSingleAttachmentToInv(sp, attachments[0]);
351 // If the attachment point isn't the same as the one previously used 380 attachments.RemoveAt(0);
352 // set it's offset position = 0 so that it appears on the attachment point 381 }
353 // and not in a weird location somewhere unknown.
354 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
355 {
356 attachPos = Vector3.Zero;
357 }
358 382
359 // AttachmentPt 0 means the client chose to 'wear' the attachment. 383 // If we're not appending, remove the rest as well
360 if (attachmentPt == 0) 384 if (attachments.Count != 0 && !append)
385 {
386 foreach (SceneObjectGroup g in attachments)
361 { 387 {
362 // Check object for stored attachment point 388 if (g.FromItemID != UUID.Zero)
363 attachmentPt = group.AttachmentPoint; 389 DetachSingleAttachmentToInv(sp, g);
364 } 390 }
391 }
365 392
366 // if we still didn't find a suitable attachment point....... 393 lock (sp.AttachmentsSyncLock)
367 if (attachmentPt == 0) 394 {
368 {
369 // Stick it on left hand with Zero Offset from the attachment point.
370 attachmentPt = (uint)AttachmentPoint.LeftHand;
371 attachPos = Vector3.Zero;
372 }
373
374 if (useAttachData)
375 {
376 group.RootPart.RotationOffset = group.RootPart.AttachRotation;
377 attachPos = group.RootPart.AttachOffset;
378 if (attachmentPt == 0)
379 {
380 attachmentPt = group.RootPart.AttachPoint;
381 if (attachmentPt == 0)
382 {
383 attachmentPt = (uint)AttachmentPoint.LeftHand;
384 attachPos = Vector3.Zero;
385 }
386 }
387 else if (group.RootPart.AttachPoint != attachmentPt)
388 {
389 attachPos = Vector3.Zero;
390 }
391 }
392 group.AttachmentPoint = attachmentPt; 395 group.AttachmentPoint = attachmentPt;
393 group.AbsolutePosition = attachPos; 396 group.AbsolutePosition = attachPos;
394 397
@@ -396,6 +399,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
396 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append); 399 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
397 400
398 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 401 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
402
403 if (resumeScripts)
404 {
405 // Fire after attach, so we don't get messy perms dialogs
406 // 4 == AttachedRez
407 group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
408 group.ResumeScripts();
409 }
410
411 // Do this last so that event listeners have access to all the effects of the attachment
412 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
399 } 413 }
400 414
401 return true; 415 return true;
@@ -425,8 +439,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
425 return null; 439 return null;
426 440
427// m_log.DebugFormat( 441// m_log.DebugFormat(
428// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", 442// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
429// (AttachmentPoint)AttachmentPt, itemID, sp.Name); 443// (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
430 444
431 bool append = (AttachmentPt & 0x80) != 0; 445 bool append = (AttachmentPt & 0x80) != 0;
432 AttachmentPt &= 0x7f; 446 AttachmentPt &= 0x7f;
@@ -558,6 +572,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
558 return; 572 return;
559 } 573 }
560 574
575// m_log.DebugFormat(
576// "[ATTACHMENTS MODULE]: Detaching object {0} {1} for {2} in {3}",
577// so.Name, so.LocalId, sp.Name, m_scene.Name);
578
561 // Scripts MUST be snapshotted before the object is 579 // Scripts MUST be snapshotted before the object is
562 // removed from the scene because doing otherwise will 580 // removed from the scene because doing otherwise will
563 // clobber the run flag 581 // clobber the run flag
@@ -879,79 +897,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
879 return null; 897 return null;
880 } 898 }
881 899
882 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 900 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
883 901 objatt.HasGroupChanged = false;
884 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones 902 bool tainted = false;
885 while (attachments.Count >= 5) 903 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
886 { 904 tainted = true;
887 if (attachments[0].FromItemID != UUID.Zero) 905
888 DetachSingleAttachmentToInv(sp, attachments[0]); 906 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
889 attachments.RemoveAt(0); 907 // course of events. If not, then it's probably not worth trying to recover the situation
890 } 908 // since this is more likely to trigger further exceptions and confuse later debugging. If
891 909 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
892 // If we're not appending, remove the rest as well 910 // since other normal error conditions will simply return false instead.
893 if (attachments.Count != 0 && !append) 911 // This will throw if the attachment fails
894 { 912 try
895 foreach (SceneObjectGroup g in attachments)
896 {
897 if (g.FromItemID != UUID.Zero)
898 DetachSingleAttachmentToInv(sp, g);
899 }
900 }
901
902 lock (sp.AttachmentsSyncLock)
903 { 913 {
904// m_log.DebugFormat(
905// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
906// objatt.Name, sp.Name, attachmentPt, m_scene.Name);
907
908 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
909 objatt.HasGroupChanged = false;
910 bool tainted = false;
911 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
912 tainted = true;
913
914 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
915 // course of events. If not, then it's probably not worth trying to recover the situation
916 // since this is more likely to trigger further exceptions and confuse later debugging. If
917 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
918 // since other normal error conditions will simply return false instead.
919 // This will throw if the attachment fails
920 try
921 {
922 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false, append);
923 }
924 catch (Exception e)
925 {
926 m_log.ErrorFormat(
927 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
928 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
929
930 // Make sure the object doesn't stick around and bail
931 sp.RemoveAttachment(objatt);
932 m_scene.DeleteSceneObject(objatt, false);
933 return null;
934 }
935
936 if (tainted)
937 objatt.HasGroupChanged = true;
938
939 if (doc != null) 914 if (doc != null)
940 { 915 {
941 objatt.LoadScriptState(doc); 916 objatt.LoadScriptState(doc);
942 objatt.ResetOwnerChangeFlag(); 917 objatt.ResetOwnerChangeFlag();
943 } 918 }
944 919
945 // Fire after attach, so we don't get messy perms dialogs 920 AttachObjectInternal(sp, objatt, attachmentPt, false, true, false, append);
946 // 4 == AttachedRez 921 }
947 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 922 catch (Exception e)
948 objatt.ResumeScripts(); 923 {
949 924 m_log.ErrorFormat(
950 // Do this last so that event listeners have access to all the effects of the attachment 925 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
951 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); 926 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
952 927
953 return objatt; 928 // Make sure the object doesn't stick around and bail
929 sp.RemoveAttachment(objatt);
930 m_scene.DeleteSceneObject(objatt, false);
931 return null;
954 } 932 }
933
934 if (tainted)
935 objatt.HasGroupChanged = true;
936
937 return objatt;
955 } 938 }
956 939
957 /// <summary> 940 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 545aeda..da4bc83 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -228,6 +228,120 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); 228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
229 } 229 }
230 230
231 [Test]
232 public void TestWearAttachmentFromGround()
233 {
234 TestHelpers.InMethod();
235// TestHelpers.EnableLogging();
236
237 Scene scene = CreateTestScene();
238 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
239 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
240
241 SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID);
242
243 {
244 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
245
246 m_numberOfAttachEventsFired = 0;
247 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, false);
248
249 // Check status on scene presence
250 Assert.That(sp.HasAttachments(), Is.True);
251 List<SceneObjectGroup> attachments = sp.GetAttachments();
252 Assert.That(attachments.Count, Is.EqualTo(1));
253 SceneObjectGroup attSo = attachments[0];
254 Assert.That(attSo.Name, Is.EqualTo(so.Name));
255 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
256 Assert.That(attSo.IsAttachment);
257 Assert.That(attSo.UsesPhysics, Is.False);
258 Assert.That(attSo.IsTemporary, Is.False);
259
260 // Check item status
261 Assert.That(
262 sp.Appearance.GetAttachpoint(attSo.FromItemID),
263 Is.EqualTo((int)AttachmentPoint.LeftHand));
264
265 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
266 Assert.That(attachmentItem, Is.Not.Null);
267 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name));
268
269 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
270 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
271
272 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2));
273
274 // Check events
275 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
276 }
277
278 // Test wearing a different attachment from the ground.
279 {
280 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false);
281
282 // Check status on scene presence
283 Assert.That(sp.HasAttachments(), Is.True);
284 List<SceneObjectGroup> attachments = sp.GetAttachments();
285 Assert.That(attachments.Count, Is.EqualTo(1));
286 SceneObjectGroup attSo = attachments[0];
287 Assert.That(attSo.Name, Is.EqualTo(so2.Name));
288 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
289 Assert.That(attSo.IsAttachment);
290 Assert.That(attSo.UsesPhysics, Is.False);
291 Assert.That(attSo.IsTemporary, Is.False);
292
293 // Check item status
294 Assert.That(
295 sp.Appearance.GetAttachpoint(attSo.FromItemID),
296 Is.EqualTo((int)AttachmentPoint.LeftHand));
297
298 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
299 Assert.That(attachmentItem, Is.Not.Null);
300 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
301
302 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
303 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
304
305 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
306
307 // Check events
308 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
309 }
310
311 // Test rewearing an already worn attachment from ground. Nothing should happen.
312 {
313 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false);
314
315 // Check status on scene presence
316 Assert.That(sp.HasAttachments(), Is.True);
317 List<SceneObjectGroup> attachments = sp.GetAttachments();
318 Assert.That(attachments.Count, Is.EqualTo(1));
319 SceneObjectGroup attSo = attachments[0];
320 Assert.That(attSo.Name, Is.EqualTo(so2.Name));
321 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
322 Assert.That(attSo.IsAttachment);
323 Assert.That(attSo.UsesPhysics, Is.False);
324 Assert.That(attSo.IsTemporary, Is.False);
325
326 // Check item status
327 Assert.That(
328 sp.Appearance.GetAttachpoint(attSo.FromItemID),
329 Is.EqualTo((int)AttachmentPoint.LeftHand));
330
331 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
332 Assert.That(attachmentItem, Is.Not.Null);
333 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
334
335 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
336 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
337
338 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
339
340 // Check events
341 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
342 }
343 }
344
231 /// <summary> 345 /// <summary>
232 /// Test that we do not attempt to attach an in-world object that someone else is sitting on. 346 /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
233 /// </summary> 347 /// </summary>
@@ -275,29 +389,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
275 389
276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 390 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
277 391
278 m_numberOfAttachEventsFired = 0; 392 {
279 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 393 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
280 sp, attItem.ID, (uint)AttachmentPoint.Chest); 394 sp, attItem.ID, (uint)AttachmentPoint.Chest);
281 395
282 // Check scene presence status 396 // Check scene presence status
283 Assert.That(sp.HasAttachments(), Is.True); 397 Assert.That(sp.HasAttachments(), Is.True);
284 List<SceneObjectGroup> attachments = sp.GetAttachments(); 398 List<SceneObjectGroup> attachments = sp.GetAttachments();
285 Assert.That(attachments.Count, Is.EqualTo(1)); 399 Assert.That(attachments.Count, Is.EqualTo(1));
286 SceneObjectGroup attSo = attachments[0]; 400 SceneObjectGroup attSo = attachments[0];
287 Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); 401 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
288 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 402 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
289 Assert.That(attSo.IsAttachment); 403 Assert.That(attSo.IsAttachment);
290 Assert.That(attSo.UsesPhysics, Is.False); 404 Assert.That(attSo.UsesPhysics, Is.False);
291 Assert.That(attSo.IsTemporary, Is.False); 405 Assert.That(attSo.IsTemporary, Is.False);
406
407 // Check appearance status
408 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
409 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
410 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
411
412 // Check events
413 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
414 }
415
416 // Test attaching an already attached attachment
417 {
418 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
419 sp, attItem.ID, (uint)AttachmentPoint.Chest);
292 420
293 // Check appearance status 421 // Check scene presence status
294 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 422 Assert.That(sp.HasAttachments(), Is.True);
295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 423 List<SceneObjectGroup> attachments = sp.GetAttachments();
424 Assert.That(attachments.Count, Is.EqualTo(1));
425 SceneObjectGroup attSo = attachments[0];
426 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
427 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
428 Assert.That(attSo.IsAttachment);
429 Assert.That(attSo.UsesPhysics, Is.False);
430 Assert.That(attSo.IsTemporary, Is.False);
431
432 // Check appearance status
433 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
434 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
435 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
436
437 // Check events
438 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
439 }
440 }
296 441
297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 442 /// <summary>
443 /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point
444 /// </summary>
445 [Test]
446 public void TestWearAttachmentFromInventory()
447 {
448 TestHelpers.InMethod();
449// TestHelpers.EnableLogging();
298 450
299 // Check events 451 Scene scene = CreateTestScene();
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); 452 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
453 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
454
455 InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20);
456 InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21);
457
458 {
459 m_numberOfAttachEventsFired = 0;
460 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default);
461
462 // default attachment point is currently the left hand.
463 Assert.That(sp.HasAttachments(), Is.True);
464 List<SceneObjectGroup> attachments = sp.GetAttachments();
465 Assert.That(attachments.Count, Is.EqualTo(1));
466 SceneObjectGroup attSo = attachments[0];
467 Assert.That(attSo.Name, Is.EqualTo(attItem1.Name));
468 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
469 Assert.That(attSo.IsAttachment);
470
471 // Check appearance status
472 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
473 Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
474 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
475
476 // Check events
477 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
478 }
479
480 // Test wearing a second attachment at the same position
481 // Until multiple attachments at one point is implemented, this will remove the first attachment
482 // This test relies on both attachments having the same default attachment point (in this case LeftHand
483 // since none other has been set).
484 {
485 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
486
487 // default attachment point is currently the left hand.
488 Assert.That(sp.HasAttachments(), Is.True);
489 List<SceneObjectGroup> attachments = sp.GetAttachments();
490 Assert.That(attachments.Count, Is.EqualTo(1));
491 SceneObjectGroup attSo = attachments[0];
492 Assert.That(attSo.Name, Is.EqualTo(attItem2.Name));
493 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
494 Assert.That(attSo.IsAttachment);
495
496 // Check appearance status
497 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
498 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
499 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
500
501 // Check events
502 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
503 }
504
505 // Test wearing an already attached attachment
506 {
507 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
508
509 // default attachment point is currently the left hand.
510 Assert.That(sp.HasAttachments(), Is.True);
511 List<SceneObjectGroup> attachments = sp.GetAttachments();
512 Assert.That(attachments.Count, Is.EqualTo(1));
513 SceneObjectGroup attSo = attachments[0];
514 Assert.That(attSo.Name, Is.EqualTo(attItem2.Name));
515 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
516 Assert.That(attSo.IsAttachment);
517
518 // Check appearance status
519 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
520 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
521 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
522
523 // Check events
524 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
525 }
301 } 526 }
302 527
303 /// <summary> 528 /// <summary>