aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar
diff options
context:
space:
mode:
authorubit2013-04-28 20:40:11 +0200
committerubit2013-04-28 20:40:11 +0200
commit61ea7ee5a94e5e3d33fc77c1c316318850309c42 (patch)
tree1e589fc3b448b580d1cc25b52215ef5ce2d7ae78 /OpenSim/Region/CoreModules/Avatar
parentMerge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork (diff)
parentController module for dynamic floaters (WIP) (diff)
downloadopensim-SC-61ea7ee5a94e5e3d33fc77c1c316318850309c42.zip
opensim-SC-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.gz
opensim-SC-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.bz2
opensim-SC-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.xz
Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork
Conflicts: bin/Regions/Regions.ini.example
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs659
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs283
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs13
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs32
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs22
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs86
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs (renamed from OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs)149
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs194
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs (renamed from OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs)265
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs138
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
19 files changed, 1215 insertions, 689 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 7cc5092..cb724aa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
49 { 49 {
50 #region INonSharedRegionModule 50 #region INonSharedRegionModule
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 public int DebugLevel { get; set; }
52 54
53 private Scene m_scene; 55 private Scene m_scene;
54 private IInventoryAccessModule m_invAccessModule; 56 private IInventoryAccessModule m_invAccessModule;
@@ -76,10 +78,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
76 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
77 79
78 if (Enabled) 80 if (Enabled)
81 {
79 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
85
86 MainConsole.Instance.Commands.AddCommand(
87 "Debug",
88 false,
89 "debug attachments",
90 "debug attachments [0|1]",
91 "Turn on attachments debugging\n"
92 + " <= 0 - turns off debugging\n"
93 + " >= 1 - turns on attachment message logging\n",
94 HandleDebugAttachments);
95 }
80 96
81 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
82 } 98 }
99
100 private void HandleDebugAttachments(string module, string[] args)
101 {
102 int debugLevel;
103
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
105 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]");
107 }
108 else
109 {
110 DebugLevel = debugLevel;
111 MainConsole.Instance.OutputFormat(
112 "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.Name);
113 }
114 }
115
116 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary>
119 /// <param name='localID'></param>
120 /// <param name='itemID'></param>
121 private void HandleScriptStateChange(uint localID, bool started)
122 {
123 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
124 if (sog != null && sog.IsAttachment)
125 {
126 if (!started)
127 {
128 // FIXME: This is a convoluted way for working out whether the script state has changed to stop
129 // because it has been manually stopped or because the stop was called in UpdateDetachedObject() below
130 // This needs to be handled in a less tangled way.
131 ScenePresence sp = m_scene.GetScenePresence(sog.AttachedAvatar);
132 if (sp.ControllingClient.IsActive)
133 sog.HasGroupChanged = true;
134 }
135 else
136 {
137 sog.HasGroupChanged = true;
138 }
139 }
140 }
83 141
84 public void RemoveRegion(Scene scene) 142 public void RemoveRegion(Scene scene)
85 { 143 {
@@ -153,10 +211,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
153 } 211 }
154 } 212 }
155 213
156 /// <summary>
157 /// RezAttachments. This should only be called upon login on the first region.
158 /// Attachment rezzings on crossings and TPs are done in a different way.
159 /// </summary>
160 public void RezAttachments(IScenePresence sp) 214 public void RezAttachments(IScenePresence sp)
161 { 215 {
162 if (!Enabled) 216 if (!Enabled)
@@ -165,10 +219,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
165 if (null == sp.Appearance) 219 if (null == sp.Appearance)
166 { 220 {
167 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID); 221 m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
222
168 return; 223 return;
169 } 224 }
170 225
171// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name); 226 if (sp.GetAttachments().Count > 0)
227 {
228 if (DebugLevel > 0)
229 m_log.DebugFormat(
230 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments",
231 m_scene.Name, sp.Name);
232
233 return;
234 }
235
236 if (DebugLevel > 0)
237 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
172 238
173 XmlDocument doc = new XmlDocument(); 239 XmlDocument doc = new XmlDocument();
174 string stateData = String.Empty; 240 string stateData = String.Empty;
@@ -235,10 +301,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
235 301
236 // If we're an NPC then skip all the item checks and manipulations since we don't have an 302 // If we're an NPC then skip all the item checks and manipulations since we don't have an
237 // inventory right now. 303 // inventory right now.
238 if (sp.PresenceType == PresenceType.Npc) 304 RezSingleAttachmentFromInventoryInternal(
239 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true); 305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null);
240 else
241 RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
242 } 306 }
243 catch (Exception e) 307 catch (Exception e)
244 { 308 {
@@ -254,14 +318,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
254 if (!Enabled) 318 if (!Enabled)
255 return; 319 return;
256 320
257// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); 321 if (DebugLevel > 0)
322 m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
323
324 List<SceneObjectGroup> attachments = sp.GetAttachments();
325
326 if (attachments.Count <= 0)
327 return;
328
329 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
330
331 foreach (SceneObjectGroup so in attachments)
332 {
333 // Scripts MUST be snapshotted before the object is
334 // removed from the scene because doing otherwise will
335 // clobber the run flag
336 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
337 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
338 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
339 }
258 340
259 lock (sp.AttachmentsSyncLock) 341 lock (sp.AttachmentsSyncLock)
260 { 342 {
261 foreach (SceneObjectGroup so in sp.GetAttachments()) 343 foreach (SceneObjectGroup so in attachments)
262 { 344 UpdateDetachedObject(sp, so, scriptStates[so]);
263 UpdateDetachedObject(sp, so);
264 }
265 345
266 sp.ClearAttachments(); 346 sp.ClearAttachments();
267 } 347 }
@@ -272,9 +352,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
272 if (!Enabled) 352 if (!Enabled)
273 return; 353 return;
274 354
275// m_log.DebugFormat( 355 if (DebugLevel > 0)
276// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", 356 m_log.DebugFormat(
277// m_scene.RegionInfo.RegionName, sp.Name, silent); 357 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
358 m_scene.RegionInfo.RegionName, sp.Name, silent);
278 359
279 foreach (SceneObjectGroup sop in sp.GetAttachments()) 360 foreach (SceneObjectGroup sop in sp.GetAttachments())
280 { 361 {
@@ -284,110 +365,95 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
284 sp.ClearAttachments(); 365 sp.ClearAttachments();
285 } 366 }
286 367
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append) 368 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
288 { 369 {
289 if (!Enabled) 370 if (!Enabled)
290 return false; 371 return false;
291 372
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, append)) 373 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true;
296 }
297
298 return false;
299 } 374 }
300 375
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append) 376 /// <summary>
377 /// Internal method which actually does all the work for attaching an object.
378 /// </summary>
379 /// <returns>The object attached.</returns>
380 /// <param name='sp'></param>
381 /// <param name='group'>The object to attach.</param>
382 /// <param name='attachmentPt'></param>
383 /// <param name='silent'></param>
384 /// <param name='addToInventory'>If true then add object to user inventory.</param>
385 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
386 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
302 { 387 {
303 lock (sp.AttachmentsSyncLock)
304 {
305// m_log.DebugFormat( 388// m_log.DebugFormat(
306// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 389// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
307// group.Name, group.LocalId, sp.Name, attachmentPt, silent); 390// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
308 391
309 if (group.GetSittingAvatarsCount() != 0) 392 if (sp.GetAttachments().Contains(group))
310 { 393 {
311// m_log.WarnFormat( 394// m_log.WarnFormat(
312// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", 395// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
313// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); 396// group.Name, group.LocalId, sp.Name, AttachmentPt);
314
315 return false;
316 }
317
318 if (sp.GetAttachments(attachmentPt).Contains(group))
319 {
320 // m_log.WarnFormat(
321 // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
322 // group.Name, group.LocalId, sp.Name, AttachmentPt);
323
324 return false;
325 }
326
327 Vector3 attachPos = group.AbsolutePosition;
328
329 // If the attachment point isn't the same as the one previously used
330 // set it's offset position = 0 so that it appears on the attachment point
331 // and not in a weird location somewhere unknown.
332 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
333 {
334 attachPos = Vector3.Zero;
335 }
336
337 // AttachmentPt 0 means the client chose to 'wear' the attachment.
338 if (attachmentPt == 0)
339 {
340 // Check object for stored attachment point
341 attachmentPt = group.AttachmentPoint;
342 }
343
344 // if we still didn't find a suitable attachment point.......
345 if (attachmentPt == 0)
346 {
347 // Stick it on left hand with Zero Offset from the attachment point.
348 attachmentPt = (uint)AttachmentPoint.LeftHand;
349 attachPos = Vector3.Zero;
350 }
351
352 if (useAttachData)
353 {
354 group.RootPart.RotationOffset = group.RootPart.AttachRotation;
355 attachPos = group.RootPart.AttachOffset;
356 if (attachmentPt == 0)
357 {
358 attachmentPt = group.RootPart.AttachPoint;
359 if (attachmentPt == 0)
360 {
361 attachmentPt = (uint)AttachmentPoint.LeftHand;
362 attachPos = Vector3.Zero;
363 }
364 }
365 else if (group.RootPart.AttachPoint != attachmentPt)
366 {
367 attachPos = Vector3.Zero;
368 }
369 }
370 group.AttachmentPoint = attachmentPt;
371 group.AbsolutePosition = attachPos;
372 397
373 if (sp.PresenceType != PresenceType.Npc) 398 return false;
374 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
375
376 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
377 } 399 }
378 400
379 return true; 401 if (group.GetSittingAvatarsCount() != 0)
380 } 402 {
403 if (DebugLevel > 0)
404 m_log.WarnFormat(
405 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
406 group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
407
408 return false;
409 }
410
411 Vector3 attachPos = group.AbsolutePosition;
412
413 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
414 // be removed when that functionality is implemented in opensim
415 attachmentPt &= 0x7f;
416
417 // If the attachment point isn't the same as the one previously used
418 // set it's offset position = 0 so that it appears on the attachment point
419 // and not in a weird location somewhere unknown.
420 if (attachmentPt != (uint)AttachmentPoint.Default && attachmentPt != group.AttachmentPoint)
421 {
422 attachPos = Vector3.Zero;
423 }
424
425 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment.
426 if (attachmentPt == (uint)AttachmentPoint.Default)
427 {
428 // Check object for stored attachment point
429 attachmentPt = group.AttachmentPoint;
430 }
431
432 // if we still didn't find a suitable attachment point.......
433 if (attachmentPt == 0)
434 {
435 // Stick it on left hand with Zero Offset from the attachment point.
436 attachmentPt = (uint)AttachmentPoint.LeftHand;
437 attachPos = Vector3.Zero;
438 }
381 439
382 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append)
383 {
384 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 440 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
385 441
442 if (attachments.Contains(group))
443 {
444 if (DebugLevel > 0)
445 m_log.WarnFormat(
446 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
447 group.Name, group.LocalId, sp.Name, attachmentPt);
448
449 return false;
450 }
451
386 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones 452 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
387 while (attachments.Count >= 5) 453 while (attachments.Count >= 5)
388 { 454 {
389 if (attachments[0].FromItemID != UUID.Zero) 455 if (attachments[0].FromItemID != UUID.Zero)
390 DetachSingleAttachmentToInvInternal(sp, attachments[0]); 456 DetachSingleAttachmentToInv(sp, attachments[0]);
391 attachments.RemoveAt(0); 457 attachments.RemoveAt(0);
392 } 458 }
393 459
@@ -397,19 +463,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
397 foreach (SceneObjectGroup g in attachments) 463 foreach (SceneObjectGroup g in attachments)
398 { 464 {
399 if (g.FromItemID != UUID.Zero) 465 if (g.FromItemID != UUID.Zero)
400 DetachSingleAttachmentToInvInternal(sp, g); 466 DetachSingleAttachmentToInv(sp, g);
401 } 467 }
402 } 468 }
403 469
404 // Add the new attachment to inventory if we don't already have it. 470 lock (sp.AttachmentsSyncLock)
405 if (!temp)
406 { 471 {
407 UUID newAttachmentItemID = group.FromItemID; 472 group.AttachmentPoint = attachmentPt;
408 if (newAttachmentItemID == UUID.Zero) 473 group.AbsolutePosition = attachPos;
409 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
410 474
411 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 475 if (addToInventory && sp.PresenceType != PresenceType.Npc)
476 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
477
478 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
479
480 if (resumeScripts)
481 {
482 // Fire after attach, so we don't get messy perms dialogs
483 // 4 == AttachedRez
484 group.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
485 group.ResumeScripts();
486 }
487
488 // Do this last so that event listeners have access to all the effects of the attachment
489 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
412 } 490 }
491
492 return true;
493 }
494
495 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool append)
496 {
497 // Add the new attachment to inventory if we don't already have it.
498 UUID newAttachmentItemID = group.FromItemID;
499 if (newAttachmentItemID == UUID.Zero)
500 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
501
502 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
413 } 503 }
414 504
415 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 505 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
@@ -422,40 +512,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
422 if (!Enabled) 512 if (!Enabled)
423 return null; 513 return null;
424 514
425// m_log.DebugFormat( 515 if (DebugLevel > 0)
426// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", 516 m_log.DebugFormat(
427// (AttachmentPoint)AttachmentPt, itemID, sp.Name); 517 "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
428 518 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
429 bool append = (AttachmentPt & 0x80) != 0;
430 AttachmentPt &= 0x7f;
431 519
432 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). 520 // We check the attachments in the avatar appearance here rather than the objects attached to the
433 // This often happens during login - not sure the exact reason. 521 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are
434 // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the 522 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done
435 // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login 523 // because pre-outfit folder viewers (most version 1 viewers) require it.
436 // before anything has actually been attached.
437 bool alreadyOn = false; 524 bool alreadyOn = false;
438 List<SceneObjectGroup> existingAttachments = sp.GetAttachments(); 525 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
439 foreach (SceneObjectGroup so in existingAttachments) 526 foreach (AvatarAttachment existingAttachment in existingAttachments)
440 { 527 {
441 if (so.FromItemID == itemID) 528 if (existingAttachment.ItemID == itemID)
442 { 529 {
443 alreadyOn = true; 530 alreadyOn = true;
444 break; 531 break;
445 } 532 }
446 } 533 }
447 534
448// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
449 if (alreadyOn) 535 if (alreadyOn)
450 { 536 {
451// m_log.WarnFormat( 537 if (DebugLevel > 0)
452// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", 538 m_log.DebugFormat(
453// sp.Name, itemID, AttachmentPt); 539 "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
540 sp.Name, itemID, AttachmentPt);
454 541
455 return null; 542 return null;
456 } 543 }
457 544
458 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc, append); 545 bool append = (AttachmentPt & 0x80) != 0;
546 AttachmentPt &= 0x7f;
547
548 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
459 } 549 }
460 550
461 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 551 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -463,13 +553,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
463 if (!Enabled) 553 if (!Enabled)
464 return; 554 return;
465 555
466 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); 556 if (DebugLevel > 0)
467 lock (sp.AttachmentsSyncLock) 557 m_log.DebugFormat(
558 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}",
559 rezlist.Count, sp.Name, m_scene.Name);
560
561 foreach (KeyValuePair<UUID, uint> rez in rezlist)
468 { 562 {
469 foreach (KeyValuePair<UUID, uint> rez in rezlist) 563 RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value);
470 {
471 RezSingleAttachmentFromInventory(sp, rez.Key, rez.Value);
472 }
473 } 564 }
474 } 565 }
475 566
@@ -483,9 +574,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
483 if (!Enabled) 574 if (!Enabled)
484 return; 575 return;
485 576
486// m_log.DebugFormat( 577 if (DebugLevel > 0)
487// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 578 m_log.DebugFormat(
488// sp.UUID, soLocalId); 579 "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
580 sp.UUID, soLocalId);
489 581
490 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 582 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
491 583
@@ -501,9 +593,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
501 if (inventoryID == UUID.Zero) 593 if (inventoryID == UUID.Zero)
502 return; 594 return;
503 595
504// m_log.DebugFormat( 596 if (DebugLevel > 0)
505// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", 597 m_log.DebugFormat(
506// so.Name, so.LocalId, inventoryID); 598 "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
599 so.Name, so.LocalId, inventoryID);
507 600
508 lock (sp.AttachmentsSyncLock) 601 lock (sp.AttachmentsSyncLock)
509 { 602 {
@@ -549,25 +642,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
549 642
550 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 643 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
551 { 644 {
645 if (so.AttachedAvatar != sp.UUID)
646 {
647 m_log.WarnFormat(
648 "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
649 so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
650
651 return;
652 }
653
654 if (DebugLevel > 0)
655 m_log.DebugFormat(
656 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
657 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
658
659 // Scripts MUST be snapshotted before the object is
660 // removed from the scene because doing otherwise will
661 // clobber the run flag
662 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
663 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
664 string scriptedState = PrepareScriptInstanceForSave(so, true);
665
552 lock (sp.AttachmentsSyncLock) 666 lock (sp.AttachmentsSyncLock)
553 { 667 {
554 // Save avatar attachment information 668 // Save avatar attachment information
555// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); 669// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
556 670
557 if (so.AttachedAvatar != sp.UUID)
558 {
559 m_log.WarnFormat(
560 "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
561 so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
562
563 return;
564 }
565
566 bool changed = sp.Appearance.DetachAttachment(so.FromItemID); 671 bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
567 if (changed && m_scene.AvatarFactory != null) 672 if (changed && m_scene.AvatarFactory != null)
568 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 673 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
569 674
570 DetachSingleAttachmentToInvInternal(sp, so); 675 sp.RemoveAttachment(so);
676 UpdateDetachedObject(sp, so, scriptedState);
571 } 677 }
572 } 678 }
573 679
@@ -674,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
674 780
675 grp.HasGroupChanged = false; // Prevent it being saved over and over 781 grp.HasGroupChanged = false; // Prevent it being saved over and over
676 } 782 }
677// else 783 else if (DebugLevel > 0)
678// { 784 {
679// m_log.DebugFormat( 785 m_log.DebugFormat(
680// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", 786 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
681// grp.UUID, grp.AttachmentPoint); 787 grp.UUID, grp.AttachmentPoint);
682// } 788 }
683 } 789 }
684 790
685 /// <summary> 791 /// <summary>
@@ -697,9 +803,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
697 private void AttachToAgent( 803 private void AttachToAgent(
698 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 804 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
699 { 805 {
700// m_log.DebugFormat( 806 if (DebugLevel > 0)
701// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 807 m_log.DebugFormat(
702// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 808 "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
809 so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
703 810
704 so.DetachFromBackup(); 811 so.DetachFromBackup();
705 812
@@ -722,19 +829,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
722 829
723 if (!silent) 830 if (!silent)
724 { 831 {
725 // Killing it here will cause the client to deselect it 832 if (so.HasPrivateAttachmentPoint)
726 // It then reappears on the avatar, deselected
727 // through the full update below
728 //
729 if (so.IsSelected)
730 {
731 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
732 }
733 else if (so.HasPrivateAttachmentPoint)
734 { 833 {
735// m_log.DebugFormat( 834 if (DebugLevel > 0)
736// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}", 835 m_log.DebugFormat(
737// so.Name, sp.Name, so.AttachmentPoint); 836 "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
837 so.Name, sp.Name, so.AttachmentPoint);
738 838
739 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the 839 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the
740 // scene that it's no longer in their awareness. 840 // scene that it's no longer in their awareness.
@@ -745,7 +845,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 }); 845 });
746 } 846 }
747 847
748 so.IsSelected = false; // fudge.... 848 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update
849 // will succeed, as that will not update if an attachment is selected.
850 so.IsSelected = false; // fudge....
851
749 so.ScheduleGroupForFullUpdate(); 852 so.ScheduleGroupForFullUpdate();
750 } 853 }
751 854
@@ -765,9 +868,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
765 if (m_invAccessModule == null) 868 if (m_invAccessModule == null)
766 return null; 869 return null;
767 870
768 // m_log.DebugFormat( 871 if (DebugLevel > 0)
769 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 872 m_log.DebugFormat(
770 // grp.Name, grp.LocalId, remoteClient.Name); 873 "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
874 grp.Name, grp.LocalId, sp.Name);
771 875
772 InventoryItemBase newItem 876 InventoryItemBase newItem
773 = m_invAccessModule.CopyToInventory( 877 = m_invAccessModule.CopyToInventory(
@@ -782,8 +886,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
782 return newItem; 886 return newItem;
783 } 887 }
784 888
785 private string GetObjectScriptStates(SceneObjectGroup grp) 889 /// <summary>
890 /// Prepares the script instance for save.
891 /// </summary>
892 /// <remarks>
893 /// This involves triggering the detach event and getting the script state (which also stops the script)
894 /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a
895 /// running script is performing attachment operations.
896 /// </remarks>
897 /// <returns>
898 /// The script state ready for persistence.
899 /// </returns>
900 /// <param name='grp'>
901 /// </param>
902 /// <param name='fireDetachEvent'>
903 /// If true, then fire the script event before we save its state.
904 /// </param>
905 private string PrepareScriptInstanceForSave(SceneObjectGroup grp, bool fireDetachEvent)
786 { 906 {
907 if (fireDetachEvent)
908 m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero);
909
787 using (StringWriter sw = new StringWriter()) 910 using (StringWriter sw = new StringWriter())
788 { 911 {
789 using (XmlTextWriter writer = new XmlTextWriter(sw)) 912 using (XmlTextWriter writer = new XmlTextWriter(sw))
@@ -795,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
795 } 918 }
796 } 919 }
797 920
798 private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) 921 private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so, string scriptedState)
799 { 922 {
800 // Don't save attachments for HG visitors, it 923 // Don't save attachments for HG visitors, it
801 // messes up their inventory. When a HG visitor logs 924 // messes up their inventory. When a HG visitor logs
@@ -808,11 +931,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
808 && (m_scene.UserManagementModule == null 931 && (m_scene.UserManagementModule == null
809 || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); 932 || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID));
810 933
811 // Scripts MUST be snapshotted before the object is
812 // removed from the scene because doing otherwise will
813 // clobber the run flag
814 string scriptedState = GetObjectScriptStates(so);
815
816 // Remove the object from the scene so no more updates 934 // Remove the object from the scene so no more updates
817 // are sent. Doing this before the below changes will ensure 935 // are sent. Doing this before the below changes will ensure
818 // updates can't cause "HUD artefacts" 936 // updates can't cause "HUD artefacts"
@@ -836,97 +954,75 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
836 so.RemoveScriptInstances(true); 954 so.RemoveScriptInstances(true);
837 } 955 }
838 956
839 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
840 {
841 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
842
843 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
844 sp.RemoveAttachment(so);
845
846 UpdateDetachedObject(sp, so);
847 }
848
849 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 957 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
850 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc, bool append) 958 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
851 { 959 {
852 if (m_invAccessModule == null) 960 if (m_invAccessModule == null)
853 return null; 961 return null;
854 962
855 lock (sp.AttachmentsSyncLock) 963 SceneObjectGroup objatt;
964
965 if (itemID != UUID.Zero)
966 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
967 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
968 false, false, sp.UUID, true);
969 else
970 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
971 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
972 false, false, sp.UUID, true);
973
974 if (objatt == null)
856 { 975 {
857 SceneObjectGroup objatt; 976 m_log.WarnFormat(
977 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
978 itemID, sp.Name, attachmentPt);
858 979
859 if (itemID != UUID.Zero) 980 return null;
860 objatt = m_invAccessModule.RezObject(sp.ControllingClient, 981 }
861 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
862 false, false, sp.UUID, true);
863 else
864 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
865 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
866 false, false, sp.UUID, true);
867 982
868 if (objatt != null) 983 if (DebugLevel > 0)
984 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name);
987
988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
989 objatt.HasGroupChanged = false;
990 bool tainted = false;
991 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
992 tainted = true;
993
994 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
995 // course of events. If not, then it's probably not worth trying to recover the situation
996 // since this is more likely to trigger further exceptions and confuse later debugging. If
997 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
998 // since other normal error conditions will simply return false instead.
999 // This will throw if the attachment fails
1000 try
1001 {
1002 if (doc != null)
869 { 1003 {
870// m_log.DebugFormat( 1004 objatt.LoadScriptState(doc);
871// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", 1005 objatt.ResetOwnerChangeFlag();
872// objatt.Name, sp.Name, attachmentPt, m_scene.Name); 1006 }
873
874 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
875 objatt.HasGroupChanged = false;
876 bool tainted = false;
877 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
878 tainted = true;
879
880 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
881 // course of events. If not, then it's probably not worth trying to recover the situation
882 // since this is more likely to trigger further exceptions and confuse later debugging. If
883 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
884 // since other normal error conditions will simply return false instead.
885 // This will throw if the attachment fails
886 try
887 {
888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false, append);
889 }
890 catch (Exception e)
891 {
892 m_log.ErrorFormat(
893 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
894 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
895
896 // Make sure the object doesn't stick around and bail
897 sp.RemoveAttachment(objatt);
898 m_scene.DeleteSceneObject(objatt, false);
899 return null;
900 }
901
902 if (tainted)
903 objatt.HasGroupChanged = true;
904 1007
905 if (doc != null) 1008 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
906 { 1009 }
907 objatt.LoadScriptState(doc); 1010 catch (Exception e)
908 objatt.ResetOwnerChangeFlag(); 1011 {
909 } 1012 m_log.ErrorFormat(
1013 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
1014 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
910 1015
911 // Fire after attach, so we don't get messy perms dialogs 1016 // Make sure the object doesn't stick around and bail
912 // 4 == AttachedRez 1017 sp.RemoveAttachment(objatt);
913 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); 1018 m_scene.DeleteSceneObject(objatt, false);
914 objatt.ResumeScripts(); 1019 return null;
1020 }
915 1021
916 // Do this last so that event listeners have access to all the effects of the attachment 1022 if (tainted)
917 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); 1023 objatt.HasGroupChanged = true;
918 1024
919 return objatt; 1025 return objatt;
920 }
921 else
922 {
923 m_log.WarnFormat(
924 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
925 itemID, sp.Name, attachmentPt);
926 }
927 }
928
929 return null;
930 } 1026 }
931 1027
932 /// <summary> 1028 /// <summary>
@@ -963,9 +1059,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
963 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID); 1059 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
964 if (changed && m_scene.AvatarFactory != null) 1060 if (changed && m_scene.AvatarFactory != null)
965 { 1061 {
966// m_log.DebugFormat( 1062 if (DebugLevel > 0)
967// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()", 1063 m_log.DebugFormat(
968// sp.Name, att.Name, AttachmentPt); 1064 "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
1065 sp.Name, att.Name, AttachmentPt);
969 1066
970 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 1067 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
971 } 1068 }
@@ -980,9 +1077,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
980 if (!Enabled) 1077 if (!Enabled)
981 return null; 1078 return null;
982 1079
983 // m_log.DebugFormat( 1080 if (DebugLevel > 0)
984 // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", 1081 m_log.DebugFormat(
985 // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); 1082 "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
1083 (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
986 1084
987 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1085 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
988 1086
@@ -1013,9 +1111,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1013 1111
1014 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) 1112 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
1015 { 1113 {
1016// m_log.DebugFormat( 1114 if (DebugLevel > 0)
1017// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", 1115 m_log.DebugFormat(
1018// objectLocalID, remoteClient.Name, AttachmentPt, silent); 1116 "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
1117 objectLocalID, remoteClient.Name, AttachmentPt, silent);
1019 1118
1020 if (!Enabled) 1119 if (!Enabled)
1021 return; 1120 return;
@@ -1048,11 +1147,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1048 AttachmentPt &= 0x7f; 1147 AttachmentPt &= 0x7f;
1049 1148
1050 // Calls attach with a Zero position 1149 // Calls attach with a Zero position
1051 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false, append)) 1150 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, false, append))
1052 { 1151 {
1053// m_log.Debug( 1152 if (DebugLevel > 0)
1054// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 1153 m_log.Debug(
1055// + ", AttachmentPoint: " + AttachmentPt); 1154 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
1155 + ", AttachmentPoint: " + AttachmentPt);
1056 1156
1057 // Save avatar attachment information 1157 // Save avatar attachment information
1058 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1158 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
@@ -1084,17 +1184,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1084 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1184 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
1085 if (sp != null) 1185 if (sp != null)
1086 { 1186 {
1087 lock (sp.AttachmentsSyncLock) 1187 List<SceneObjectGroup> attachments = sp.GetAttachments();
1188
1189 foreach (SceneObjectGroup group in attachments)
1088 { 1190 {
1089 List<SceneObjectGroup> attachments = sp.GetAttachments(); 1191 if (group.FromItemID == itemID && group.FromItemID != UUID.Zero)
1090
1091 foreach (SceneObjectGroup group in attachments)
1092 { 1192 {
1093 if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) 1193 DetachSingleAttachmentToInv(sp, group);
1094 { 1194 return;
1095 DetachSingleAttachmentToInv(sp, group);
1096 return;
1097 }
1098 } 1195 }
1099 } 1196 }
1100 } 1197 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 545aeda..1a38619 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -130,7 +130,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
130 config.AddConfig("Modules"); 130 config.AddConfig("Modules");
131 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 131 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
132 132
133 modules.Add(new AttachmentsModule()); 133 AttachmentsModule attMod = new AttachmentsModule();
134 attMod.DebugLevel = 1;
135 modules.Add(attMod);
134 modules.Add(new BasicInventoryAccessModule()); 136 modules.Add(new BasicInventoryAccessModule());
135 } 137 }
136 138
@@ -197,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 199 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 200
199 m_numberOfAttachEventsFired = 0; 201 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false); 202 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
201 203
202 // Check status on scene presence 204 // Check status on scene presence
203 Assert.That(sp.HasAttachments(), Is.True); 205 Assert.That(sp.HasAttachments(), Is.True);
@@ -228,6 +230,120 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); 230 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
229 } 231 }
230 232
233 [Test]
234 public void TestWearAttachmentFromGround()
235 {
236 TestHelpers.InMethod();
237// TestHelpers.EnableLogging();
238
239 Scene scene = CreateTestScene();
240 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
241 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
242
243 SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID);
244
245 {
246 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
247
248 m_numberOfAttachEventsFired = 0;
249 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
250
251 // Check status on scene presence
252 Assert.That(sp.HasAttachments(), Is.True);
253 List<SceneObjectGroup> attachments = sp.GetAttachments();
254 Assert.That(attachments.Count, Is.EqualTo(1));
255 SceneObjectGroup attSo = attachments[0];
256 Assert.That(attSo.Name, Is.EqualTo(so.Name));
257 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
258 Assert.That(attSo.IsAttachment);
259 Assert.That(attSo.UsesPhysics, Is.False);
260 Assert.That(attSo.IsTemporary, Is.False);
261
262 // Check item status
263 Assert.That(
264 sp.Appearance.GetAttachpoint(attSo.FromItemID),
265 Is.EqualTo((int)AttachmentPoint.LeftHand));
266
267 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
268 Assert.That(attachmentItem, Is.Not.Null);
269 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name));
270
271 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
272 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
273
274 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2));
275
276 // Check events
277 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
278 }
279
280 // Test wearing a different attachment from the ground.
281 {
282 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
283
284 // Check status on scene presence
285 Assert.That(sp.HasAttachments(), Is.True);
286 List<SceneObjectGroup> attachments = sp.GetAttachments();
287 Assert.That(attachments.Count, Is.EqualTo(1));
288 SceneObjectGroup attSo = attachments[0];
289 Assert.That(attSo.Name, Is.EqualTo(so2.Name));
290 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
291 Assert.That(attSo.IsAttachment);
292 Assert.That(attSo.UsesPhysics, Is.False);
293 Assert.That(attSo.IsTemporary, Is.False);
294
295 // Check item status
296 Assert.That(
297 sp.Appearance.GetAttachpoint(attSo.FromItemID),
298 Is.EqualTo((int)AttachmentPoint.LeftHand));
299
300 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
301 Assert.That(attachmentItem, Is.Not.Null);
302 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
303
304 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
305 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
306
307 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
308
309 // Check events
310 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
311 }
312
313 // Test rewearing an already worn attachment from ground. Nothing should happen.
314 {
315 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
316
317 // Check status on scene presence
318 Assert.That(sp.HasAttachments(), Is.True);
319 List<SceneObjectGroup> attachments = sp.GetAttachments();
320 Assert.That(attachments.Count, Is.EqualTo(1));
321 SceneObjectGroup attSo = attachments[0];
322 Assert.That(attSo.Name, Is.EqualTo(so2.Name));
323 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
324 Assert.That(attSo.IsAttachment);
325 Assert.That(attSo.UsesPhysics, Is.False);
326 Assert.That(attSo.IsTemporary, Is.False);
327
328 // Check item status
329 Assert.That(
330 sp.Appearance.GetAttachpoint(attSo.FromItemID),
331 Is.EqualTo((int)AttachmentPoint.LeftHand));
332
333 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
334 Assert.That(attachmentItem, Is.Not.Null);
335 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
336
337 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
338 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
339
340 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
341
342 // Check events
343 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
344 }
345 }
346
231 /// <summary> 347 /// <summary>
232 /// Test that we do not attempt to attach an in-world object that someone else is sitting on. 348 /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
233 /// </summary> 349 /// </summary>
@@ -254,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
254 sp2.AbsolutePosition = new Vector3(0, 0, 0); 370 sp2.AbsolutePosition = new Vector3(0, 0, 0);
255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 371 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
256 372
257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false); 373 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
258 374
259 Assert.That(sp.HasAttachments(), Is.False); 375 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 376 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -275,29 +391,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
275 391
276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 392 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
277 393
278 m_numberOfAttachEventsFired = 0; 394 {
279 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 395 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
280 sp, attItem.ID, (uint)AttachmentPoint.Chest); 396 sp, attItem.ID, (uint)AttachmentPoint.Chest);
281 397
282 // Check scene presence status 398 // Check scene presence status
283 Assert.That(sp.HasAttachments(), Is.True); 399 Assert.That(sp.HasAttachments(), Is.True);
284 List<SceneObjectGroup> attachments = sp.GetAttachments(); 400 List<SceneObjectGroup> attachments = sp.GetAttachments();
285 Assert.That(attachments.Count, Is.EqualTo(1)); 401 Assert.That(attachments.Count, Is.EqualTo(1));
286 SceneObjectGroup attSo = attachments[0]; 402 SceneObjectGroup attSo = attachments[0];
287 Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); 403 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
288 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 404 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
289 Assert.That(attSo.IsAttachment); 405 Assert.That(attSo.IsAttachment);
290 Assert.That(attSo.UsesPhysics, Is.False); 406 Assert.That(attSo.UsesPhysics, Is.False);
291 Assert.That(attSo.IsTemporary, Is.False); 407 Assert.That(attSo.IsTemporary, Is.False);
408
409 // Check appearance status
410 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
411 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
412 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
413
414 // Check events
415 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
416 }
417
418 // Test attaching an already attached attachment
419 {
420 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
421 sp, attItem.ID, (uint)AttachmentPoint.Chest);
292 422
293 // Check appearance status 423 // Check scene presence status
294 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 424 Assert.That(sp.HasAttachments(), Is.True);
295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 425 List<SceneObjectGroup> attachments = sp.GetAttachments();
426 Assert.That(attachments.Count, Is.EqualTo(1));
427 SceneObjectGroup attSo = attachments[0];
428 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
429 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
430 Assert.That(attSo.IsAttachment);
431 Assert.That(attSo.UsesPhysics, Is.False);
432 Assert.That(attSo.IsTemporary, Is.False);
433
434 // Check appearance status
435 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
436 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
437 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
438
439 // Check events
440 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
441 }
442 }
296 443
297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 444 /// <summary>
445 /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point
446 /// </summary>
447 [Test]
448 public void TestWearAttachmentFromInventory()
449 {
450 TestHelpers.InMethod();
451// TestHelpers.EnableLogging();
298 452
299 // Check events 453 Scene scene = CreateTestScene();
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); 454 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
455 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
456
457 InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20);
458 InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21);
459
460 {
461 m_numberOfAttachEventsFired = 0;
462 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default);
463
464 // default attachment point is currently the left hand.
465 Assert.That(sp.HasAttachments(), Is.True);
466 List<SceneObjectGroup> attachments = sp.GetAttachments();
467 Assert.That(attachments.Count, Is.EqualTo(1));
468 SceneObjectGroup attSo = attachments[0];
469 Assert.That(attSo.Name, Is.EqualTo(attItem1.Name));
470 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
471 Assert.That(attSo.IsAttachment);
472
473 // Check appearance status
474 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
475 Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
476 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
477
478 // Check events
479 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
480 }
481
482 // Test wearing a second attachment at the same position
483 // Until multiple attachments at one point is implemented, this will remove the first attachment
484 // This test relies on both attachments having the same default attachment point (in this case LeftHand
485 // since none other has been set).
486 {
487 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
488
489 // default attachment point is currently the left hand.
490 Assert.That(sp.HasAttachments(), Is.True);
491 List<SceneObjectGroup> attachments = sp.GetAttachments();
492 Assert.That(attachments.Count, Is.EqualTo(1));
493 SceneObjectGroup attSo = attachments[0];
494 Assert.That(attSo.Name, Is.EqualTo(attItem2.Name));
495 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
496 Assert.That(attSo.IsAttachment);
497
498 // Check appearance status
499 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
500 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
501 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
502
503 // Check events
504 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
505 }
506
507 // Test wearing an already attached attachment
508 {
509 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
510
511 // default attachment point is currently the left hand.
512 Assert.That(sp.HasAttachments(), Is.True);
513 List<SceneObjectGroup> attachments = sp.GetAttachments();
514 Assert.That(attachments.Count, Is.EqualTo(1));
515 SceneObjectGroup attSo = attachments[0];
516 Assert.That(attSo.Name, Is.EqualTo(attItem2.Name));
517 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand));
518 Assert.That(attSo.IsAttachment);
519
520 // Check appearance status
521 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
522 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
523 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
524
525 // Check events
526 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3));
527 }
301 } 528 }
302 529
303 /// <summary> 530 /// <summary>
@@ -503,7 +730,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
503 public void TestRezAttachmentsOnAvatarEntrance() 730 public void TestRezAttachmentsOnAvatarEntrance()
504 { 731 {
505 TestHelpers.InMethod(); 732 TestHelpers.InMethod();
506// log4net.Config.XmlConfigurator.Configure(); 733// TestHelpers.EnableLogging();
507 734
508 Scene scene = CreateTestScene(); 735 Scene scene = CreateTestScene();
509 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 736 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
@@ -604,7 +831,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
604 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 831 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
605 832
606 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
607 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager); 834
835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
836 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager);
837 List<TestClient> destinationTestClients = new List<TestClient>();
838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients);
839
840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager);
608 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); 841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
609 842
610 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); 843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
@@ -623,7 +856,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
623 teleportLookAt, 856 teleportLookAt,
624 (uint)TeleportFlags.ViaLocation); 857 (uint)TeleportFlags.ViaLocation);
625 858
626 ((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide(); 859 destinationTestClients[0].CompleteMovement();
627 860
628 // Check attachments have made it into sceneB 861 // Check attachments have made it into sceneB
629 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); 862 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 1adff7e..bc79944 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41 41
42using Mono.Addins; 42using Mono.Addins;
43using PermissionMask = OpenSim.Framework.PermissionMask;
43 44
44namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 45namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
45{ 46{
@@ -322,6 +323,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
322 323
323 if (asset != null) 324 if (asset != null)
324 { 325 {
326 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
327 asset.ID = asset.FullID.ToString();
328
325 asset.Temporary = false; 329 asset.Temporary = false;
326 asset.Local = false; 330 asset.Local = false;
327 m_scene.AssetService.Store(asset); 331 m_scene.AssetService.Store(asset);
@@ -358,7 +362,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
358 362
359 public void QueueAppearanceSave(UUID agentid) 363 public void QueueAppearanceSave(UUID agentid)
360 { 364 {
361 // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); 365// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
362 366
363 // 10000 ticks per millisecond, 1000 milliseconds per second 367 // 10000 ticks per millisecond, 1000 milliseconds per second
364 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); 368 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
@@ -655,7 +659,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
655 return; 659 return;
656 } 660 }
657 661
658 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); 662// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
659 663
660 // This could take awhile since it needs to pull inventory 664 // This could take awhile since it needs to pull inventory
661 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape 665 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
@@ -664,6 +668,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
664 // multiple save requests. 668 // multiple save requests.
665 SetAppearanceAssets(sp.UUID, sp.Appearance); 669 SetAppearanceAssets(sp.UUID, sp.Appearance);
666 670
671// List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
672// foreach (AvatarAttachment att in attachments)
673// {
674// m_log.DebugFormat(
675// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
676// sp.Name, att.ItemID, att.AttachPoint);
677// }
678
667 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 679 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
668 680
669 // Trigger this here because it's the final step in the set/queue/save process for appearance setting. 681 // Trigger this here because it's the final step in the set/queue/save process for appearance setting.
@@ -1087,7 +1099,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1087 } 1099 }
1088 1100
1089 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); 1101 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
1090 outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); 1102 outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
1091 } 1103 }
1092 } 1104 }
1093} 1105}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index e21547c..f090e15 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common.Mock;
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class AvatarFactoryModuleTests 42 public class AvatarFactoryModuleTests : OpenSimTestCase
43 { 43 {
44 /// <summary> 44 /// <summary>
45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. 45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service.
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 4c3f1cc..174642d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
256 // If camera is moved into client, then camera position can be used 256 // If camera is moved into client, then camera position can be used
257 // MT: No, it can't, as chat is heard from the avatar position, not 257 // MT: No, it can't, as chat is heard from the avatar position, not
258 // the camera position. 258 // the camera position.
259 s.ForEachRootScenePresence( 259 s.ForEachScenePresence(
260 delegate(ScenePresence presence) 260 delegate(ScenePresence presence)
261 { 261 {
262 if (destination != UUID.Zero && presence.UUID != destination) 262 if (destination != UUID.Zero && presence.UUID != destination)
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index 5ec0ea9..b44a5c9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
38using Mono.Addins; 38using Mono.Addins;
39using PermissionMask = OpenSim.Framework.PermissionMask;
39 40
40namespace OpenSim.Region.CoreModules.Avatar.Friends 41namespace OpenSim.Region.CoreModules.Avatar.Friends
41{ 42{
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 7a197f7..961117e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests 40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class FriendsModuleTests 43 public class FriendsModuleTests : OpenSimTestCase
44 { 44 {
45 private FriendsModule m_fm; 45 private FriendsModule m_fm;
46 private TestScene m_scene; 46 private TestScene m_scene;
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 9fa9be1..fa8c3f3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -67,9 +67,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
67 protected Scene m_scene; 67 protected Scene m_scene;
68 protected IDialogModule m_dialogModule; 68 protected IDialogModule m_dialogModule;
69 69
70 protected Dictionary<UUID, string> m_capsDict =
71 new Dictionary<UUID, string>();
72
73 protected IDialogModule DialogModule 70 protected IDialogModule DialogModule
74 { 71 {
75 get 72 get
@@ -91,7 +88,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
91 m_scene.RegisterModuleInterface<IGodsModule>(this); 88 m_scene.RegisterModuleInterface<IGodsModule>(this);
92 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 89 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
93 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 90 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
94 m_scene.EventManager.OnClientClosed += OnClientClosed;
95 scene.EventManager.OnIncomingInstantMessage += 91 scene.EventManager.OnIncomingInstantMessage +=
96 OnIncomingInstantMessage; 92 OnIncomingInstantMessage;
97 } 93 }
@@ -127,15 +123,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
127 client.OnRequestGodlikePowers -= RequestGodlikePowers; 123 client.OnRequestGodlikePowers -= RequestGodlikePowers;
128 } 124 }
129 125
130 private void OnClientClosed(UUID agentID, Scene scene)
131 {
132 m_capsDict.Remove(agentID);
133 }
134
135 private void OnRegisterCaps(UUID agentID, Caps caps) 126 private void OnRegisterCaps(UUID agentID, Caps caps)
136 { 127 {
137 string uri = "/CAPS/" + UUID.Random(); 128 string uri = "/CAPS/" + UUID.Random();
138 m_capsDict[agentID] = uri;
139 129
140 caps.RegisterHandler("UntrustedSimulatorMessage", 130 caps.RegisterHandler("UntrustedSimulatorMessage",
141 new RestStreamHandler("POST", uri, 131 new RestStreamHandler("POST", uri,
@@ -288,8 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
288 if (sp.IsChildAgent) 278 if (sp.IsChildAgent)
289 return; 279 return;
290 sp.ControllingClient.Kick(reason); 280 sp.ControllingClient.Kick(reason);
291 sp.MakeChildAgent(); 281 sp.Scene.IncomingCloseAgent(sp.UUID, true);
292 sp.ControllingClient.Close();
293 } 282 }
294 283
295 private void OnIncomingInstantMessage(GridInstantMessage msg) 284 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index cc266df..1627f6c 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
153 if (sp != null && !sp.IsChildAgent) 153 if (sp != null && !sp.IsChildAgent)
154 { 154 {
155 // Local message 155 // Local message
156 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 156// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
157 157
158 sp.ControllingClient.SendInstantMessage(im); 158 sp.ControllingClient.SendInstantMessage(im);
159 159
@@ -166,14 +166,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
166 // try child avatar second 166 // try child avatar second
167 foreach (Scene scene in m_Scenes) 167 foreach (Scene scene in m_Scenes)
168 { 168 {
169 //m_log.DebugFormat( 169// m_log.DebugFormat(
170 // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 170// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
171 171
172 ScenePresence sp = scene.GetScenePresence(toAgentID); 172 ScenePresence sp = scene.GetScenePresence(toAgentID);
173 if (sp != null) 173 if (sp != null)
174 { 174 {
175 // Local message 175 // Local message
176 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); 176// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
177 177
178 sp.ControllingClient.SendInstantMessage(im); 178 sp.ControllingClient.SendInstantMessage(im);
179 179
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
183 } 183 }
184 } 184 }
185 185
186 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 187
188 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
189 } 189 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 3a44cc5..2d46276 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -189,20 +189,24 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
189 { 189 {
190 foreach (GridInstantMessage im in msglist) 190 foreach (GridInstantMessage im in msglist)
191 { 191 {
192 // client.SendInstantMessage(im); 192 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
193 193 // send it directly or else the item will be given twice
194 // Send through scene event manager so all modules get a chance 194 client.SendInstantMessage(im);
195 // to look at this message before it gets delivered. 195 else
196 // 196 {
197 // Needed for proper state management for stored group 197 // Send through scene event manager so all modules get a chance
198 // invitations 198 // to look at this message before it gets delivered.
199 // 199 //
200 200 // Needed for proper state management for stored group
201 im.offline = 1; 201 // invitations
202 202 //
203 Scene s = FindScene(client.AgentId); 203
204 if (s != null) 204 im.offline = 1;
205 s.EventManager.TriggerIncomingInstantMessage(im); 205
206 Scene s = FindScene(client.AgentId);
207 if (s != null)
208 s.EventManager.TriggerIncomingInstantMessage(im);
209 }
206 } 210 }
207 } 211 }
208 } 212 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index dc2b0e0..659b178 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -161,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
161 string filePath = "ERROR"; 161 string filePath = "ERROR";
162 162
163 List<InventoryFolderBase> folderCandidates 163 List<InventoryFolderBase> folderCandidates
164 = InventoryArchiveUtils.FindFolderByPath( 164 = InventoryArchiveUtils.FindFoldersByPath(
165 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); 165 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath);
166 166
167 if (folderCandidates.Count == 0) 167 if (folderCandidates.Count == 0)
@@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
296 // iar name and try to find that instead. 296 // iar name and try to find that instead.
297 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 297 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
298 List<InventoryFolderBase> folderCandidates 298 List<InventoryFolderBase> folderCandidates
299 = InventoryArchiveUtils.FindFolderByPath( 299 = InventoryArchiveUtils.FindFoldersByPath(
300 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); 300 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath);
301 301
302 if (folderCandidates.Count != 0) 302 if (folderCandidates.Count != 0)
@@ -487,6 +487,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
487 { 487 {
488// m_log.DebugFormat( 488// m_log.DebugFormat(
489// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); 489// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
490
491 if (coa.Objects.Count == 0)
492 {
493 m_log.WarnFormat(
494 "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of coalesced object from asset {0} as it has zero loaded components",
495 assetId);
496 return false;
497 }
490 498
491 sceneObjects.AddRange(coa.Objects); 499 sceneObjects.AddRange(coa.Objects);
492 } 500 }
@@ -495,7 +503,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
495 SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 503 SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
496 504
497 if (deserializedObject != null) 505 if (deserializedObject != null)
506 {
498 sceneObjects.Add(deserializedObject); 507 sceneObjects.Add(deserializedObject);
508 }
509 else
510 {
511 m_log.WarnFormat(
512 "[INVENTORY ARCHIVE READ REQUEST]: Aborting load of object from asset {0} as deserialization failed",
513 assetId);
514
515 return false;
516 }
499 } 517 }
500 518
501 foreach (SceneObjectGroup sog in sceneObjects) 519 foreach (SceneObjectGroup sog in sceneObjects)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
index 0d90a15..dbaf2aa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -52,13 +52,82 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
52 /// <summary> 52 /// <summary>
53 /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder 53 /// Find a folder given a PATH_DELIMITER delimited path starting from a user's root folder
54 /// </summary> 54 /// </summary>
55 /// <remarks>
56 /// This method does not handle paths that contain multiple delimitors
57 ///
58 /// FIXME: We have no way of distinguishing folders with the same path
55 /// 59 ///
60 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
61 /// </remarks>
62 /// <param name="inventoryService">
63 /// Inventory service to query
64 /// </param>
65 /// <param name="userId">
66 /// User id to search
67 /// </param>
68 /// <param name="path">
69 /// The path to the required folder.
70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
71 /// </param>
72 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
73 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
74 public static InventoryFolderBase FindFolderByPath(
75 IInventoryService inventoryService, UUID userId, string path)
76 {
77 List<InventoryFolderBase> folders = FindFoldersByPath(inventoryService, userId, path);
78
79 if (folders.Count == 0)
80 return null;
81 else
82 return folders[0];
83 }
84
85 /// <summary>
86 /// Find a folder given a PATH_DELIMITER delimited path starting from a given folder
87 /// </summary>
88 /// <remarks>
56 /// This method does not handle paths that contain multiple delimitors 89 /// This method does not handle paths that contain multiple delimitors
57 /// 90 ///
58 /// FIXME: We have no way of distinguishing folders with the same path 91 /// FIXME: We have no way of distinguishing folders with the same path
59 /// 92 ///
60 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 93 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
94 /// </remarks>
95 /// <param name="inventoryService">
96 /// Inventory service to query
97 /// </param>
98 /// <param name="startFolder">
99 /// The folder from which the path starts
100 /// </param>
101 /// <param name="path">
102 /// The path to the required folder.
103 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
104 /// </param>
105 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
106 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
107 public static InventoryFolderBase FindFolderByPath(
108 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
109 {
110 if (null == startFolder)
111 return null;
112
113 List<InventoryFolderBase> folders = FindFoldersByPath(inventoryService, startFolder, path);
114
115 if (folders.Count == 0)
116 return null;
117 else
118 return folders[0];
119 }
120
121 /// <summary>
122 /// Find a set of folders given a PATH_DELIMITER delimited path starting from a user's root folder
123 /// </summary>
124 /// <remarks>
125 /// This method does not handle paths that contain multiple delimitors
126 ///
127 /// FIXME: We have no way of distinguishing folders with the same path
61 /// 128 ///
129 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
130 /// </remarks>
62 /// <param name="inventoryService"> 131 /// <param name="inventoryService">
63 /// Inventory service to query 132 /// Inventory service to query
64 /// </param> 133 /// </param>
@@ -70,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 139 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
71 /// </param> 140 /// </param>
72 /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> 141 /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns>
73 public static List<InventoryFolderBase> FindFolderByPath( 142 public static List<InventoryFolderBase> FindFoldersByPath(
74 IInventoryService inventoryService, UUID userId, string path) 143 IInventoryService inventoryService, UUID userId, string path)
75 { 144 {
76 InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); 145 InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId);
@@ -78,19 +147,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 if (null == rootFolder) 147 if (null == rootFolder)
79 return new List<InventoryFolderBase>(); 148 return new List<InventoryFolderBase>();
80 149
81 return FindFolderByPath(inventoryService, rootFolder, path); 150 return FindFoldersByPath(inventoryService, rootFolder, path);
82 } 151 }
83 152
84 /// <summary> 153 /// <summary>
85 /// Find a folder given a PATH_DELIMITER delimited path starting from this folder 154 /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder
86 /// </summary> 155 /// </summary>
87 /// 156 /// <remarks>
88 /// This method does not handle paths that contain multiple delimitors 157 /// This method does not handle paths that contain multiple delimitors
89 /// 158 ///
90 /// FIXME: We have no way of distinguishing folders with the same path. 159 /// FIXME: We have no way of distinguishing folders with the same path.
91 /// 160 ///
92 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 161 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
93 /// 162 /// </remarks>
94 /// <param name="inventoryService"> 163 /// <param name="inventoryService">
95 /// Inventory service to query 164 /// Inventory service to query
96 /// </param> 165 /// </param>
@@ -102,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
102 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 171 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
103 /// </param> 172 /// </param>
104 /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns> 173 /// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns>
105 public static List<InventoryFolderBase> FindFolderByPath( 174 public static List<InventoryFolderBase> FindFoldersByPath(
106 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 175 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
107 { 176 {
108 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); 177 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>();
@@ -133,12 +202,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
133 202
134 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 203 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
135 204
205// m_log.DebugFormat(
206// "Found {0} folders in {1} for {2}", contents.Folders.Count, startFolder.Name, startFolder.Owner);
207
136 foreach (InventoryFolderBase folder in contents.Folders) 208 foreach (InventoryFolderBase folder in contents.Folders)
137 { 209 {
138 if (folder.Name == components[0]) 210 if (folder.Name == components[0])
139 { 211 {
140 if (components.Length > 1) 212 if (components.Length > 1)
141 foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); 213 foundFolders.AddRange(FindFoldersByPath(inventoryService, folder, components[1]));
142 else 214 else
143 foundFolders.Add(folder); 215 foundFolders.Add(folder);
144 } 216 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index d0e88f6..4ec8ae7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
124 SaveAssets = true; 124 SaveAssets = true;
125 } 125 }
126 126
127 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) 127 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut)
128 { 128 {
129 Exception reportedException = null; 129 Exception reportedException = null;
130 bool succeeded = true; 130 bool succeeded = true;
@@ -143,6 +143,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
143 m_saveStream.Close(); 143 m_saveStream.Close();
144 } 144 }
145 145
146 if (timedOut)
147 {
148 succeeded = false;
149 reportedException = new Exception("Loading assets timed out");
150 }
151
146 m_module.TriggerInventoryArchiveSaved( 152 m_module.TriggerInventoryArchiveSaved(
147 m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); 153 m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException);
148 } 154 }
@@ -266,6 +272,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
266 saveFolderContentsOnly = true; 272 saveFolderContentsOnly = true;
267 maxComponentIndex--; 273 maxComponentIndex--;
268 } 274 }
275 else if (maxComponentIndex == -1)
276 {
277 // If the user has just specified "/", then don't save the root "My Inventory" folder. This is
278 // more intuitive then requiring the user to specify "/*" for this.
279 saveFolderContentsOnly = true;
280 }
269 281
270 m_invPath = String.Empty; 282 m_invPath = String.Empty;
271 for (int i = 0; i <= maxComponentIndex; i++) 283 for (int i = 0; i <= maxComponentIndex; i++)
@@ -283,7 +295,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
283 { 295 {
284 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); 296 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
285 List<InventoryFolderBase> candidateFolders 297 List<InventoryFolderBase> candidateFolders
286 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); 298 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath);
287 if (candidateFolders.Count > 0) 299 if (candidateFolders.Count > 0)
288 inventoryFolder = candidateFolders[0]; 300 inventoryFolder = candidateFolders[0];
289 } 301 }
@@ -350,7 +362,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
350 { 362 {
351 m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); 363 m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified");
352 364
353 ReceivedAllAssets(new List<UUID>(), new List<UUID>()); 365 ReceivedAllAssets(new List<UUID>(), new List<UUID>(), false);
354 } 366 }
355 } 367 }
356 catch (Exception) 368 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index 6eb3605..95f562e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -48,125 +48,9 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests 48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class PathTests : InventoryArchiveTestCase 51 public class InventoryArchiveLoadPathTests : InventoryArchiveTestCase
52 { 52 {
53 /// <summary> 53 /// <summary>
54 /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive
55 /// (subject to change since there is no fixed format yet).
56 /// </summary>
57 [Test]
58 public void TestSavePathToIarV0_1()
59 {
60 TestHelpers.InMethod();
61// log4net.Config.XmlConfigurator.Configure();
62
63 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
64
65 Scene scene = new SceneHelpers().SetupScene();
66 SceneHelpers.SetupSceneModules(scene, archiverModule);
67
68 // Create user
69 string userFirstName = "Jock";
70 string userLastName = "Stirrup";
71 string userPassword = "troll";
72 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
73 UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword);
74
75 // Create asset
76 SceneObjectGroup object1;
77 SceneObjectPart part1;
78 {
79 string partName = "My Little Dog Object";
80 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
81 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
82 Vector3 groupPosition = new Vector3(10, 20, 30);
83 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
84 Vector3 offsetPosition = new Vector3(5, 10, 15);
85
86 part1 = new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition);
87 part1.Name = partName;
88
89 object1 = new SceneObjectGroup(part1);
90 scene.AddNewSceneObject(object1, false);
91 }
92
93 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
94 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
95 scene.AssetService.Store(asset1);
96
97 // Create item
98 UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080");
99 InventoryItemBase item1 = new InventoryItemBase();
100 item1.Name = "My Little Dog";
101 item1.AssetID = asset1.FullID;
102 item1.ID = item1Id;
103 InventoryFolderBase objsFolder
104 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0];
105 item1.Folder = objsFolder.ID;
106 scene.AddInventoryItem(item1);
107
108 MemoryStream archiveWriteStream = new MemoryStream();
109 archiverModule.OnInventoryArchiveSaved += SaveCompleted;
110
111 // Test saving a particular path
112 mre.Reset();
113 archiverModule.ArchiveInventory(
114 Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream);
115 mre.WaitOne(60000, false);
116
117 byte[] archive = archiveWriteStream.ToArray();
118 MemoryStream archiveReadStream = new MemoryStream(archive);
119 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
120
121 //bool gotControlFile = false;
122 bool gotObject1File = false;
123 //bool gotObject2File = false;
124 string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1);
125 string expectedObject1FilePath = string.Format(
126 "{0}{1}{2}",
127 ArchiveConstants.INVENTORY_PATH,
128 InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder),
129 expectedObject1FileName);
130
131 string filePath;
132 TarArchiveReader.TarEntryType tarEntryType;
133
134// Console.WriteLine("Reading archive");
135
136 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
137 {
138// Console.WriteLine("Got {0}", filePath);
139
140// if (ArchiveConstants.CONTROL_FILE_PATH == filePath)
141// {
142// gotControlFile = true;
143// }
144
145 if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml"))
146 {
147// string fileName = filePath.Remove(0, "Objects/".Length);
148//
149// if (fileName.StartsWith(part1.Name))
150// {
151 Assert.That(expectedObject1FilePath, Is.EqualTo(filePath));
152 gotObject1File = true;
153// }
154// else if (fileName.StartsWith(part2.Name))
155// {
156// Assert.That(fileName, Is.EqualTo(expectedObject2FileName));
157// gotObject2File = true;
158// }
159 }
160 }
161
162// Assert.That(gotControlFile, Is.True, "No control file in archive");
163 Assert.That(gotObject1File, Is.True, "No item1 file in archive");
164// Assert.That(gotObject2File, Is.True, "No object2 file in archive");
165
166 // TODO: Test presence of more files and contents of files.
167 }
168
169 /// <summary>
170 /// Test loading an IAR to various different inventory paths. 54 /// Test loading an IAR to various different inventory paths.
171 /// </summary> 55 /// </summary>
172 [Test] 56 [Test]
@@ -193,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
193 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 77 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
194 78
195 // Now try loading to a root child folder 79 // Now try loading to a root child folder
196 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); 80 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false);
197 MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); 81 MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray());
198 archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); 82 archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream);
199 83
@@ -202,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
202 Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); 86 Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2");
203 87
204 // Now try loading to a more deeply nested folder 88 // Now try loading to a more deeply nested folder
205 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); 89 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC", false);
206 archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); 90 archiveReadStream = new MemoryStream(archiveReadStream.ToArray());
207 archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); 91 archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream);
208 92
@@ -287,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
287 item1.AssetID = asset1.FullID; 171 item1.AssetID = asset1.FullID;
288 item1.ID = item1Id; 172 item1.ID = item1Id;
289 InventoryFolderBase objsFolder 173 InventoryFolderBase objsFolder
290 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; 174 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0];
291 item1.Folder = objsFolder.ID; 175 item1.Folder = objsFolder.ID;
292 scene.AddInventoryItem(item1); 176 scene.AddInventoryItem(item1);
293 177
@@ -351,12 +235,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
351 foldersCreated, nodesLoaded); 235 foldersCreated, nodesLoaded);
352 236
353 List<InventoryFolderBase> folder1Candidates 237 List<InventoryFolderBase> folder1Candidates
354 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 238 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
355 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 239 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
356 240
357 InventoryFolderBase folder1 = folder1Candidates[0]; 241 InventoryFolderBase folder1 = folder1Candidates[0];
358 List<InventoryFolderBase> folder2aCandidates 242 List<InventoryFolderBase> folder2aCandidates
359 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); 243 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
360 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 244 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
361 } 245 }
362 246
@@ -368,17 +252,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
368 foldersCreated, nodesLoaded); 252 foldersCreated, nodesLoaded);
369 253
370 List<InventoryFolderBase> folder1Candidates 254 List<InventoryFolderBase> folder1Candidates
371 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 255 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
372 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 256 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
373 257
374 InventoryFolderBase folder1 = folder1Candidates[0]; 258 InventoryFolderBase folder1 = folder1Candidates[0];
375 259
376 List<InventoryFolderBase> folder2aCandidates 260 List<InventoryFolderBase> folder2aCandidates
377 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); 261 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
378 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 262 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
379 263
380 List<InventoryFolderBase> folder2bCandidates 264 List<InventoryFolderBase> folder2bCandidates
381 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2bName); 265 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName);
382 Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); 266 Assert.That(folder2bCandidates.Count, Is.EqualTo(1));
383 } 267 }
384 } 268 }
@@ -401,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
401 285
402 InventoryFolderBase folder1 286 InventoryFolderBase folder1
403 = UserInventoryHelpers.CreateInventoryFolder( 287 = UserInventoryHelpers.CreateInventoryFolder(
404 scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 288 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
405 289
406 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 290 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
407 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
@@ -414,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
414 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
415 299
416 List<InventoryFolderBase> folder1PostCandidates 300 List<InventoryFolderBase> folder1PostCandidates
417 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 301 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
418 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); 302 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2));
419 303
420 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. 304 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder.
@@ -430,7 +314,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
430// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); 314// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID));
431 315
432 List<InventoryFolderBase> folder2PostCandidates 316 List<InventoryFolderBase> folder2PostCandidates
433 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); 317 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b");
434 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 318 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
435 } 319 }
436 320
@@ -452,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
452 336
453 InventoryFolderBase folder1 337 InventoryFolderBase folder1
454 = UserInventoryHelpers.CreateInventoryFolder( 338 = UserInventoryHelpers.CreateInventoryFolder(
455 scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 339 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
456 340
457 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 341 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
458 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
@@ -465,13 +349,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
465 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
466 350
467 List<InventoryFolderBase> folder1PostCandidates 351 List<InventoryFolderBase> folder1PostCandidates
468 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 352 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
469 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); 353 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
470 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); 354 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
471 355
472 List<InventoryFolderBase> folder2PostCandidates 356 List<InventoryFolderBase> folder2PostCandidates
473 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b"); 357 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b");
474 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 358 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
475 } 359 }
476 } 360 }
477} \ No newline at end of file 361}
362
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
new file mode 100644
index 0000000..1b521fc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
@@ -0,0 +1,194 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Threading;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenSim.Data;
36using OpenSim.Framework;
37using OpenSim.Framework.Serialization;
38using OpenSim.Framework.Serialization.External;
39using OpenSim.Framework.Communications;
40using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
41using OpenSim.Region.CoreModules.World.Serialiser;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces;
45using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock;
47
48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{
50 [TestFixture]
51 public class InventoryArchiveLoadTests : InventoryArchiveTestCase
52 {
53 protected TestScene m_scene;
54 protected InventoryArchiverModule m_archiverModule;
55
56 [SetUp]
57 public override void SetUp()
58 {
59 base.SetUp();
60
61 SerialiserModule serialiserModule = new SerialiserModule();
62 m_archiverModule = new InventoryArchiverModule();
63
64 m_scene = new SceneHelpers().SetupScene();
65 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
66 }
67
68 [Test]
69 public void TestLoadCoalesecedItem()
70 {
71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging();
73
74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
76
77 InventoryItemBase coaItem
78 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName);
79
80 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1");
81
82 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID);
83
84 CoalescedSceneObjects coa;
85 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa);
86
87 Assert.That(readResult, Is.True);
88 Assert.That(coa.Count, Is.EqualTo(2));
89
90 List<SceneObjectGroup> coaObjects = coa.Objects;
91 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120")));
92 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45)));
93
94 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
95 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
96 }
97
98 /// <summary>
99 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized
100 /// objects.
101 /// </summary>
102 [Test]
103 public void TestLoadIarCreatorAccountPresent()
104 {
105 TestHelpers.InMethod();
106// log4net.Config.XmlConfigurator.Configure();
107
108 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood");
109
110 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream);
111 InventoryItemBase foundItem1
112 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name);
113
114 Assert.That(
115 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()),
116 "Loaded item non-uuid creator doesn't match original");
117 Assert.That(
118 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID),
119 "Loaded item uuid creator doesn't match original");
120 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID),
121 "Loaded item owner doesn't match inventory reciever");
122
123 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
124 string xmlData = Utils.BytesToString(asset1.Data);
125 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
126
127 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
128 }
129
130// /// <summary>
131// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
132// /// an account exists with the same name as the creator, though not the same id.
133// /// </summary>
134// [Test]
135// public void TestLoadIarV0_1SameNameCreator()
136// {
137// TestHelpers.InMethod();
138// TestHelpers.EnableLogging();
139//
140// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
141// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
142//
143// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
144// InventoryItemBase foundItem1
145// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
146//
147// Assert.That(
148// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
149// "Loaded item non-uuid creator doesn't match original");
150// Assert.That(
151// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
152// "Loaded item uuid creator doesn't match original");
153// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
154// "Loaded item owner doesn't match inventory reciever");
155//
156// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
157// string xmlData = Utils.BytesToString(asset1.Data);
158// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
159//
160// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
161// }
162
163 /// <summary>
164 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
165 /// the creator or an account with the creator's name does not exist within the system.
166 /// </summary>
167 [Test]
168 public void TestLoadIarV0_1AbsentCreator()
169 {
170 TestHelpers.InMethod();
171// log4net.Config.XmlConfigurator.Configure();
172
173 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password");
174 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream);
175
176 InventoryItemBase foundItem1
177 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
178
179 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
180 Assert.That(
181 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()),
182 "Loaded item non-uuid creator doesn't match that of the loading user");
183 Assert.That(
184 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID),
185 "Loaded item uuid creator doesn't match that of the loading user");
186
187 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
188 string xmlData = Utils.BytesToString(asset1.Data);
189 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
190
191 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID));
192 }
193 }
194} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 06f6e49..5e7e24c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests 48namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class InventoryArchiverTests : InventoryArchiveTestCase 51 public class InventoryArchiveSaveTests : InventoryArchiveTestCase
52 { 52 {
53 protected TestScene m_scene; 53 protected TestScene m_scene;
54 protected InventoryArchiverModule m_archiverModule; 54 protected InventoryArchiverModule m_archiverModule;
@@ -64,36 +64,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
64 m_scene = new SceneHelpers().SetupScene(); 64 m_scene = new SceneHelpers().SetupScene();
65 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 65 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
66 } 66 }
67
68 [Test]
69 public void TestLoadCoalesecedItem()
70 {
71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging();
73
74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
76
77 InventoryItemBase coaItem
78 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName);
79
80 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1");
81
82 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID);
83
84 CoalescedSceneObjects coa;
85 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa);
86
87 Assert.That(readResult, Is.True);
88 Assert.That(coa.Count, Is.EqualTo(2));
89
90 List<SceneObjectGroup> coaObjects = coa.Objects;
91 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120")));
92 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45)));
93
94 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
95 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
96 }
97 67
98 /// <summary> 68 /// <summary>
99 /// Test that the IAR has the required files in the right order. 69 /// Test that the IAR has the required files in the right order.
@@ -121,6 +91,139 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
121 91
122 Assert.That(iarr.ControlFileLoaded, Is.True); 92 Assert.That(iarr.ControlFileLoaded, Is.True);
123 } 93 }
94
95 [Test]
96 public void TestSaveRootFolderToIar()
97 {
98 TestHelpers.InMethod();
99// TestHelpers.EnableLogging();
100
101 string userFirstName = "Jock";
102 string userLastName = "Stirrup";
103 string userPassword = "troll";
104 UUID userId = TestHelpers.ParseTail(0x20);
105
106 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
107
108 MemoryStream archiveWriteStream = new MemoryStream();
109 m_archiverModule.OnInventoryArchiveSaved += SaveCompleted;
110
111 mre.Reset();
112 m_archiverModule.ArchiveInventory(
113 Guid.NewGuid(), userFirstName, userLastName, "/", userPassword, archiveWriteStream);
114 mre.WaitOne(60000, false);
115
116 // Test created iar
117 byte[] archive = archiveWriteStream.ToArray();
118 MemoryStream archiveReadStream = new MemoryStream(archive);
119 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
120
121// InventoryArchiveUtils.
122 bool gotObjectsFolder = false;
123
124 string objectsFolderName
125 = string.Format(
126 "{0}{1}",
127 ArchiveConstants.INVENTORY_PATH,
128 InventoryArchiveWriteRequest.CreateArchiveFolderName(
129 UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects")));
130
131 string filePath;
132 TarArchiveReader.TarEntryType tarEntryType;
133
134 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
135 {
136// Console.WriteLine("Got {0}", filePath);
137
138 // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory()
139 // XXX: But really we need to stop all that stuff being created in tests or check for such folders
140 // more thoroughly
141 if (filePath == objectsFolderName)
142 gotObjectsFolder = true;
143 }
144
145 Assert.That(gotObjectsFolder, Is.True);
146 }
147
148 [Test]
149 public void TestSaveNonRootFolderToIar()
150 {
151 TestHelpers.InMethod();
152// TestHelpers.EnableLogging();
153
154 string userFirstName = "Jock";
155 string userLastName = "Stirrup";
156 string userPassword = "troll";
157 UUID userId = TestHelpers.ParseTail(0x20);
158
159 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
160
161 // Create base folder
162 InventoryFolderBase f1
163 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true);
164
165 // Create item1
166 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5);
167 InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1");
168
169 // Create embedded folder
170 InventoryFolderBase f1_1
171 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true);
172
173 // Create embedded item
174 SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6);
175 InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1");
176
177 MemoryStream archiveWriteStream = new MemoryStream();
178 m_archiverModule.OnInventoryArchiveSaved += SaveCompleted;
179
180 mre.Reset();
181 m_archiverModule.ArchiveInventory(
182 Guid.NewGuid(), userFirstName, userLastName, "f1", userPassword, archiveWriteStream);
183 mre.WaitOne(60000, false);
184
185 // Test created iar
186 byte[] archive = archiveWriteStream.ToArray();
187 MemoryStream archiveReadStream = new MemoryStream(archive);
188 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
189
190// InventoryArchiveUtils.
191 bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false;
192
193 string f1FileName
194 = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1));
195 string f1_1FileName
196 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1));
197 string so1FileName
198 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1));
199 string so2FileName
200 = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2));
201
202 string filePath;
203 TarArchiveReader.TarEntryType tarEntryType;
204
205 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
206 {
207// Console.WriteLine("Got {0}", filePath);
208
209 if (filePath == f1FileName)
210 gotf1 = true;
211 else if (filePath == f1_1FileName)
212 gotf1_1 = true;
213 else if (filePath == so1FileName)
214 gotso1 = true;
215 else if (filePath == so2FileName)
216 gotso2 = true;
217 }
218
219// Assert.That(gotControlFile, Is.True, "No control file in archive");
220 Assert.That(gotf1, Is.True);
221 Assert.That(gotf1_1, Is.True);
222 Assert.That(gotso1, Is.True);
223 Assert.That(gotso2, Is.True);
224
225 // TODO: Test presence of more files and contents of files.
226 }
124 227
125 /// <summary> 228 /// <summary>
126 /// Test saving a single inventory item to an IAR 229 /// Test saving a single inventory item to an IAR
@@ -155,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
155 item1.AssetID = asset1.FullID; 258 item1.AssetID = asset1.FullID;
156 item1.ID = item1Id; 259 item1.ID = item1Id;
157 InventoryFolderBase objsFolder 260 InventoryFolderBase objsFolder
158 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; 261 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0];
159 item1.Folder = objsFolder.ID; 262 item1.Folder = objsFolder.ID;
160 m_scene.AddInventoryItem(item1); 263 m_scene.AddInventoryItem(item1);
161 264
@@ -250,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
250 item1.AssetID = asset1.FullID; 353 item1.AssetID = asset1.FullID;
251 item1.ID = item1Id; 354 item1.ID = item1Id;
252 InventoryFolderBase objsFolder 355 InventoryFolderBase objsFolder
253 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; 356 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0];
254 item1.Folder = objsFolder.ID; 357 item1.Folder = objsFolder.ID;
255 m_scene.AddInventoryItem(item1); 358 m_scene.AddInventoryItem(item1);
256 359
@@ -317,101 +420,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
317 420
318 // TODO: Test presence of more files and contents of files. 421 // TODO: Test presence of more files and contents of files.
319 } 422 }
320
321 /// <summary>
322 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized
323 /// objects.
324 /// </summary>
325 [Test]
326 public void TestLoadIarCreatorAccountPresent()
327 {
328 TestHelpers.InMethod();
329// log4net.Config.XmlConfigurator.Configure();
330
331 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood");
332
333 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream);
334 InventoryItemBase foundItem1
335 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name);
336
337 Assert.That(
338 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()),
339 "Loaded item non-uuid creator doesn't match original");
340 Assert.That(
341 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID),
342 "Loaded item uuid creator doesn't match original");
343 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID),
344 "Loaded item owner doesn't match inventory reciever");
345
346 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
347 string xmlData = Utils.BytesToString(asset1.Data);
348 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
349
350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
351 }
352
353// /// <summary>
354// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
355// /// an account exists with the same name as the creator, though not the same id.
356// /// </summary>
357// [Test]
358// public void TestLoadIarV0_1SameNameCreator()
359// {
360// TestHelpers.InMethod();
361// TestHelpers.EnableLogging();
362//
363// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
364// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
365//
366// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
367// InventoryItemBase foundItem1
368// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
369//
370// Assert.That(
371// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
372// "Loaded item non-uuid creator doesn't match original");
373// Assert.That(
374// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
375// "Loaded item uuid creator doesn't match original");
376// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
377// "Loaded item owner doesn't match inventory reciever");
378//
379// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
380// string xmlData = Utils.BytesToString(asset1.Data);
381// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
382//
383// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
384// }
385
386 /// <summary>
387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
388 /// the creator or an account with the creator's name does not exist within the system.
389 /// </summary>
390 [Test]
391 public void TestLoadIarV0_1AbsentCreator()
392 {
393 TestHelpers.InMethod();
394// log4net.Config.XmlConfigurator.Configure();
395
396 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password");
397 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream);
398
399 InventoryItemBase foundItem1
400 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
401
402 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
403 Assert.That(
404 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()),
405 "Loaded item non-uuid creator doesn't match that of the loading user");
406 Assert.That(
407 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID),
408 "Loaded item uuid creator doesn't match that of the loading user");
409
410 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
411 string xmlData = Utils.BytesToString(asset1.Data);
412 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
413
414 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID));
415 }
416 } 423 }
417} \ No newline at end of file 424} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 4cfa33d..ae58dfd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -316,76 +316,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
316 } 316 }
317 } 317 }
318 318
319 // Disabled for now as it looks like http://opensimulator.org/mantis/view.php?id=6311 was fixed by fixes 319 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name>
320 // to inventory folder versioning allowing the viewer to move the received folder itself as happens on the 320 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be
321 // LL grid. Doing it again server-side then wrongly does a second create and move 321 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet
322// // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name> 322 // happening, possibly because we are not sending the correct inventory update messages with the correct
323// // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis 323 // transaction IDs
324// // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously 324 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
325// // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. 325 {
326// else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 326 UUID destinationFolderID = UUID.Zero;
327// { 327
328// UUID destinationFolderID = UUID.Zero; 328 if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
329// 329 {
330// if (im.binaryBucket != null && im.binaryBucket.Length >= 16) 330 destinationFolderID = new UUID(im.binaryBucket, 0);
331// { 331 }
332// destinationFolderID = new UUID(im.binaryBucket, 0); 332
333// } 333 if (destinationFolderID != UUID.Zero)
334// 334 {
335// if (destinationFolderID != UUID.Zero) 335 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
336// { 336 if (destinationFolder == null)
337// InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); 337 {
338// if (destinationFolder == null) 338 m_log.WarnFormat(
339// { 339 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
340// m_log.WarnFormat( 340 client.Name, scene.Name, destinationFolderID);
341// "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", 341
342// client.Name, scene.Name, destinationFolderID); 342 return;
343// 343 }
344// return; 344
345// } 345 IInventoryService invService = scene.InventoryService;
346// 346
347// IInventoryService invService = scene.InventoryService; 347 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
348// 348
349// UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 349 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
350// 350 item = invService.GetItem(item);
351// InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 351 InventoryFolderBase folder = null;
352// item = invService.GetItem(item); 352 UUID? previousParentFolderID = null;
353// InventoryFolderBase folder = null; 353
354// UUID? previousParentFolderID = null; 354 if (item != null) // It's an item
355// 355 {
356// if (item != null) // It's an item 356 previousParentFolderID = item.Folder;
357// { 357 item.Folder = destinationFolderID;
358// previousParentFolderID = item.Folder; 358
359// item.Folder = destinationFolderID; 359 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
360// 360 scene.AddInventoryItem(client, item);
361// invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 361 }
362// scene.AddInventoryItem(client, item); 362 else
363// } 363 {
364// else 364 folder = new InventoryFolderBase(inventoryID, client.AgentId);
365// { 365 folder = invService.GetFolder(folder);
366// folder = new InventoryFolderBase(inventoryID, client.AgentId); 366
367// folder = invService.GetFolder(folder); 367 if (folder != null) // It's a folder
368// 368 {
369// if (folder != null) // It's a folder 369 previousParentFolderID = folder.ParentID;
370// { 370 folder.ParentID = destinationFolderID;
371// previousParentFolderID = folder.ParentID; 371 invService.MoveFolder(folder);
372// folder.ParentID = destinationFolderID; 372 }
373// invService.MoveFolder(folder); 373 }
374// } 374
375// } 375 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
376// 376 if (previousParentFolderID != null)
377// // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 377 {
378// if (previousParentFolderID != null) 378 InventoryFolderBase previousParentFolder
379// { 379 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
380// InventoryFolderBase previousParentFolder 380 previousParentFolder = invService.GetFolder(previousParentFolder);
381// = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); 381 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
382// previousParentFolder = invService.GetFolder(previousParentFolder); 382
383// scene.SendInventoryUpdate(client, previousParentFolder, true, true); 383 scene.SendInventoryUpdate(client, destinationFolder, true, true);
384// 384 }
385// scene.SendInventoryUpdate(client, destinationFolder, true, true); 385 }
386// } 386 }
387// }
388// }
389 else if ( 387 else if (
390 im.dialog == (byte)InstantMessageDialog.InventoryDeclined 388 im.dialog == (byte)InstantMessageDialog.InventoryDeclined
391 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) 389 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 232a4fe..a34f2d2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -65,7 +65,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
65 { 65 {
66 m_Enabled = true; 66 m_Enabled = true;
67 67
68 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); 68 m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
69 new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty);
70 // Legacy. Remove soon!
71 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
69 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); 72 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
70 } 73 }
71 } 74 }
@@ -151,7 +154,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
151 154
152 void OnIncomingInstantMessage(GridInstantMessage im) 155 void OnIncomingInstantMessage(GridInstantMessage im)
153 { 156 {
154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) 157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport
158 || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
155 { 159 {
156 UUID sessionID = new UUID(im.imSessionID); 160 UUID sessionID = new UUID(im.imSessionID);
157 161
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index f3adb95..0c64f19 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("[LURE]: TP invite with message {0}", message); 168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171