aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs233
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs263
2 files changed, 352 insertions, 144 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a0a7a68..c94d152 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 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, false, 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
316 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append) 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>
320 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool resumeScripts, 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, true, 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..dee8ce3 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, 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, 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, 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>