diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 233 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | 263 |
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> |