aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs553
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs473
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs189
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs33
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs92
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs124
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs7
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs8
18 files changed, 1120 insertions, 509 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index fd7cad2..394b90a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private Scene m_scene; 52 private Scene m_scene;
53 private IDialogModule m_dialogModule; 53 private IInventoryAccessModule m_invAccessModule;
54 54
55 /// <summary> 55 /// <summary>
56 /// Are attachments enabled? 56 /// Are attachments enabled?
@@ -72,7 +72,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
72 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
73 { 73 {
74 m_scene = scene; 74 m_scene = scene;
75 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
76 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 75 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
77 76
78 if (Enabled) 77 if (Enabled)
@@ -89,7 +88,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
89 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 88 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
90 } 89 }
91 90
92 public void RegionLoaded(Scene scene) {} 91 public void RegionLoaded(Scene scene)
92 {
93 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
94 }
93 95
94 public void Close() 96 public void Close()
95 { 97 {
@@ -100,6 +102,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
100 102
101 #region IAttachmentsModule 103 #region IAttachmentsModule
102 104
105 public void CopyAttachments(IScenePresence sp, AgentData ad)
106 {
107 lock (sp.AttachmentsSyncLock)
108 {
109 // Attachment objects
110 List<SceneObjectGroup> attachments = sp.GetAttachments();
111 if (attachments.Count > 0)
112 {
113 ad.AttachmentObjects = new List<ISceneObject>();
114 ad.AttachmentObjectStates = new List<string>();
115 // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
116 sp.InTransitScriptStates.Clear();
117
118 foreach (SceneObjectGroup sog in attachments)
119 {
120 // We need to make a copy and pass that copy
121 // because of transfers withn the same sim
122 ISceneObject clone = sog.CloneForNewScene();
123 // Attachment module assumes that GroupPosition holds the offsets...!
124 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
125 ((SceneObjectGroup)clone).IsAttachment = false;
126 ad.AttachmentObjects.Add(clone);
127 string state = sog.GetStateSnapshot();
128 ad.AttachmentObjectStates.Add(state);
129 sp.InTransitScriptStates.Add(state);
130 // Let's remove the scripts of the original object here
131 sog.RemoveScriptInstances(true);
132 }
133 }
134 }
135 }
136
137 public void CopyAttachments(AgentData ad, IScenePresence sp)
138 {
139 if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
140 {
141 lock (sp.AttachmentsSyncLock)
142 sp.ClearAttachments();
143
144 int i = 0;
145 foreach (ISceneObject so in ad.AttachmentObjects)
146 {
147 ((SceneObjectGroup)so).LocalId = 0;
148 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
149 so.SetState(ad.AttachmentObjectStates[i++], m_scene);
150 m_scene.IncomingCreateObject(Vector3.Zero, so);
151 }
152 }
153 }
154
103 /// <summary> 155 /// <summary>
104 /// RezAttachments. This should only be called upon login on the first region. 156 /// RezAttachments. This should only be called upon login on the first region.
105 /// Attachment rezzings on crossings and TPs are done in a different way. 157 /// Attachment rezzings on crossings and TPs are done in a different way.
@@ -185,40 +237,55 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
185 if (sp.PresenceType == PresenceType.Npc) 237 if (sp.PresenceType == PresenceType.Npc)
186 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null); 238 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null);
187 else 239 else
188 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, true, d); 240 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d);
189 } 241 }
190 catch (Exception e) 242 catch (Exception e)
191 { 243 {
192 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment: {0}{1}", e.Message, e.StackTrace); 244 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId;
245 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
246 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace);
193 } 247 }
194 } 248 }
195 } 249 }
196 250
197 public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted) 251 public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted)
198 { 252 {
199// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
200
201 if (!Enabled) 253 if (!Enabled)
202 return; 254 return;
203 255
204 foreach (SceneObjectGroup grp in sp.GetAttachments()) 256// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
257
258 lock (sp.AttachmentsSyncLock)
205 { 259 {
206 grp.IsAttachment = false; 260 foreach (SceneObjectGroup so in sp.GetAttachments())
207 grp.AbsolutePosition = grp.RootPart.AttachedPos; 261 {
208 UpdateKnownItem(sp, grp, saveAllScripted); 262 // We can only remove the script instances from the script engine after we've retrieved their xml state
209 grp.IsAttachment = true; 263 // when we update the attachment item.
264 m_scene.DeleteSceneObject(so, false, false);
265
266 if (saveChanged || saveAllScripted)
267 {
268 so.IsAttachment = false;
269 so.AbsolutePosition = so.RootPart.AttachedPos;
270 UpdateKnownItem(sp, so, saveAllScripted);
271 }
272
273 so.RemoveScriptInstances(true);
274 }
275
276 sp.ClearAttachments();
210 } 277 }
211 } 278 }
212 279
213 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 280 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
214 { 281 {
215// m_log.DebugFormat(
216// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
217// m_scene.RegionInfo.RegionName, sp.Name, silent);
218
219 if (!Enabled) 282 if (!Enabled)
220 return; 283 return;
221 284
285// m_log.DebugFormat(
286// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
287// m_scene.RegionInfo.RegionName, sp.Name, silent);
288
222 foreach (SceneObjectGroup sop in sp.GetAttachments()) 289 foreach (SceneObjectGroup sop in sp.GetAttachments())
223 { 290 {
224 sop.Scene.DeleteSceneObject(sop, silent); 291 sop.Scene.DeleteSceneObject(sop, silent);
@@ -234,6 +301,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
234// m_log.DebugFormat( 301// m_log.DebugFormat(
235// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", 302// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
236// group.Name, group.LocalId, sp.Name, attachmentPt, silent); 303// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
304
305 if (group.GetSittingAvatarsCount() != 0)
306 {
307// m_log.WarnFormat(
308// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
309// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
310
311 return false;
312 }
237 313
238 if (sp.GetAttachments(attachmentPt).Contains(group)) 314 if (sp.GetAttachments(attachmentPt).Contains(group))
239 { 315 {
@@ -294,32 +370,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
294 group.AttachmentPoint = attachmentPt; 370 group.AttachmentPoint = attachmentPt;
295 group.AbsolutePosition = attachPos; 371 group.AbsolutePosition = attachPos;
296 372
297 // We also don't want to do any of the inventory operations for an NPC.
298 if (sp.PresenceType != PresenceType.Npc) 373 if (sp.PresenceType != PresenceType.Npc)
299 { 374 UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
300 // Remove any previous attachments
301 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
302
303 // At the moment we can only deal with a single attachment
304 if (attachments.Count != 0)
305 {
306 UUID oldAttachmentItemID = attachments[0].FromItemID;
307
308 if (oldAttachmentItemID != UUID.Zero)
309 DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID);
310 else
311 m_log.WarnFormat(
312 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
313 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
314 }
315
316 // Add the new attachment to inventory if we don't already have it.
317 UUID newAttachmentItemID = group.FromItemID;
318 if (newAttachmentItemID == UUID.Zero)
319 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
320
321 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
322 }
323 375
324 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 376 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
325 } 377 }
@@ -327,12 +379,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
327 return true; 379 return true;
328 } 380 }
329 381
382 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt)
383 {
384 // Remove any previous attachments
385 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
386
387 // At the moment we can only deal with a single attachment
388 if (attachments.Count != 0)
389 {
390 if (attachments[0].FromItemID != UUID.Zero)
391 DetachSingleAttachmentToInvInternal(sp, attachments[0]);
392 else
393 m_log.WarnFormat(
394 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
395 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
396 }
397
398 // Add the new attachment to inventory if we don't already have it.
399 UUID newAttachmentItemID = group.FromItemID;
400 if (newAttachmentItemID == UUID.Zero)
401 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
402
403 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
404 }
405
330 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 406 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
331 { 407 {
332 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, true, null); 408 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
333 } 409 }
334 410
335 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) 411 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
336 { 412 {
337 if (!Enabled) 413 if (!Enabled)
338 return null; 414 return null;
@@ -371,12 +447,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
371 return null; 447 return null;
372 } 448 }
373 449
374 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); 450 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
375
376 if (att == null)
377 DetachSingleAttachmentToInv(sp, itemID);
378
379 return att;
380 } 451 }
381 452
382 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 453 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -453,18 +524,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
453 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 524 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
454 } 525 }
455 526
456 public void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID) 527 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
457 { 528 {
458 lock (sp.AttachmentsSyncLock) 529 lock (sp.AttachmentsSyncLock)
459 { 530 {
460 // Save avatar attachment information 531 // Save avatar attachment information
461 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID); 532// m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + sp.UUID + ", ItemID: " + itemID);
533
534 if (so.AttachedAvatar != sp.UUID)
535 {
536 m_log.WarnFormat(
537 "[ATTACHMENTS MODULE]: Tried to detach object {0} from {1} {2} but attached avatar id was {3} in {4}",
538 so.Name, sp.Name, sp.UUID, so.AttachedAvatar, m_scene.RegionInfo.RegionName);
462 539
463 bool changed = sp.Appearance.DetachAttachment(itemID); 540 return;
541 }
542
543 bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
464 if (changed && m_scene.AvatarFactory != null) 544 if (changed && m_scene.AvatarFactory != null)
465 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 545 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
466 546
467 DetachSingleAttachmentToInvInternal(sp, itemID); 547 DetachSingleAttachmentToInvInternal(sp, so);
468 } 548 }
469 } 549 }
470 550
@@ -473,17 +553,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
473 if (!Enabled) 553 if (!Enabled)
474 return; 554 return;
475 555
476 // First we save the
477 // attachment point information, then we update the relative
478 // positioning. Then we have to mark the object as NOT an
479 // attachment. This is necessary in order to correctly save
480 // and retrieve GroupPosition information for the attachment.
481 // Finally, we restore the object's attachment status.
482 uint attachmentPoint = sog.AttachmentPoint;
483 sog.UpdateGroupPosition(pos); 556 sog.UpdateGroupPosition(pos);
484 sog.IsAttachment = false;
485 sog.AbsolutePosition = sog.RootPart.AttachedPos;
486 sog.AttachmentPoint = attachmentPoint;
487 sog.HasGroupChanged = true; 557 sog.HasGroupChanged = true;
488 } 558 }
489 559
@@ -526,6 +596,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
526 /// </remarks> 596 /// </remarks>
527 /// <param name="sp"></param> 597 /// <param name="sp"></param>
528 /// <param name="grp"></param> 598 /// <param name="grp"></param>
599 /// <param name="saveAllScripted"></param>
529 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) 600 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted)
530 { 601 {
531 // Saving attachments for NPCs messes them up for the real owner! 602 // Saving attachments for NPCs messes them up for the real owner!
@@ -538,9 +609,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
538 609
539 if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) 610 if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts()))
540 { 611 {
541 m_log.DebugFormat( 612// m_log.DebugFormat(
542 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 613// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
543 grp.UUID, grp.AttachmentPoint); 614// grp.UUID, grp.AttachmentPoint);
544 615
545 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 616 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
546 617
@@ -571,12 +642,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
571 } 642 }
572 grp.HasGroupChanged = false; // Prevent it being saved over and over 643 grp.HasGroupChanged = false; // Prevent it being saved over and over
573 } 644 }
574 else 645// else
575 { 646// {
576 m_log.DebugFormat( 647// m_log.DebugFormat(
577 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", 648// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
578 grp.UUID, grp.AttachmentPoint); 649// grp.UUID, grp.AttachmentPoint);
579 } 650// }
580 } 651 }
581 652
582 /// <summary> 653 /// <summary>
@@ -594,9 +665,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
594 private void AttachToAgent( 665 private void AttachToAgent(
595 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 666 IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
596 { 667 {
597 // m_log.DebugFormat( 668// m_log.DebugFormat(
598 // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 669// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
599 // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 670// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
600 671
601 so.DetachFromBackup(); 672 so.DetachFromBackup();
602 673
@@ -627,6 +698,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
627 { 698 {
628 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId }); 699 m_scene.SendKillObject(new List<uint> { so.RootPart.LocalId });
629 } 700 }
701 else if (so.HasPrivateAttachmentPoint)
702 {
703// m_log.DebugFormat(
704// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
705// so.Name, sp.Name, so.AttachmentPoint);
706
707 // As this scene object can now only be seen by the attaching avatar, tell everybody else in the
708 // scene that it's no longer in their awareness.
709 m_scene.ForEachClient(
710 client =>
711 { if (client.AgentId != so.AttachedAvatar)
712 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId });
713 });
714 }
630 715
631 so.IsSelected = false; // fudge.... 716 so.IsSelected = false; // fudge....
632 so.ScheduleGroupForFullUpdate(); 717 so.ScheduleGroupForFullUpdate();
@@ -645,210 +730,124 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
645 /// <returns>The user inventory item created that holds the attachment.</returns> 730 /// <returns>The user inventory item created that holds the attachment.</returns>
646 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp) 731 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp)
647 { 732 {
733 if (m_invAccessModule == null)
734 return null;
735
648 // m_log.DebugFormat( 736 // m_log.DebugFormat(
649 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", 737 // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
650 // grp.Name, grp.LocalId, remoteClient.Name); 738 // grp.Name, grp.LocalId, remoteClient.Name);
651 739
652// Vector3 inventoryStoredPosition = new Vector3 740 InventoryItemBase newItem
653// (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 741 = m_invAccessModule.CopyToInventory(
654// ? (float)Constants.RegionSize - 6 742 DeRezAction.TakeCopy,
655// : grp.AbsolutePosition.X) 743 m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID,
656// , 744 new List<SceneObjectGroup> { grp },
657// (grp.AbsolutePosition.Y > (int)Constants.RegionSize) 745 sp.ControllingClient, true)[0];
658// ? (float)Constants.RegionSize - 6
659// : grp.AbsolutePosition.Y,
660// grp.AbsolutePosition.Z);
661//
662// Vector3 originalPosition = grp.AbsolutePosition;
663//
664// grp.AbsolutePosition = inventoryStoredPosition;
665
666 // If we're being called from a script, then trying to serialize that same script's state will not complete
667 // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
668 // the client/server crashes rather than logging out normally, the attachment's scripts will resume
669 // without state on relog. Arguably, this is what we want anyway.
670 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
671
672// grp.AbsolutePosition = originalPosition;
673
674 AssetBase asset = m_scene.CreateAsset(
675 grp.GetPartName(grp.LocalId),
676 grp.GetPartDescription(grp.LocalId),
677 (sbyte)AssetType.Object,
678 Utils.StringToBytes(sceneObjectXml),
679 sp.UUID);
680
681 m_scene.AssetService.Store(asset);
682
683 InventoryItemBase item = new InventoryItemBase();
684 item.CreatorId = grp.RootPart.CreatorID.ToString();
685 item.CreatorData = grp.RootPart.CreatorData;
686 item.Owner = sp.UUID;
687 item.ID = UUID.Random();
688 item.AssetID = asset.FullID;
689 item.Description = asset.Description;
690 item.Name = asset.Name;
691 item.AssetType = asset.Type;
692 item.InvType = (int)InventoryType.Object;
693
694 InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
695 if (folder != null)
696 item.Folder = folder.ID;
697 else // oopsies
698 item.Folder = UUID.Zero;
699
700 // Nix the special bits we used to use for slam and the folded perms
701 uint allowablePermissionsMask = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move);
702
703 if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions())
704 {
705 item.BasePermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
706 item.CurrentPermissions = grp.RootPart.BaseMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
707 item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
708 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
709 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask & allowablePermissionsMask;
710 }
711 else
712 {
713 item.BasePermissions = grp.RootPart.BaseMask & allowablePermissionsMask;
714 item.CurrentPermissions = grp.RootPart.OwnerMask & allowablePermissionsMask;
715 item.NextPermissions = grp.RootPart.NextOwnerMask & allowablePermissionsMask;
716 item.EveryOnePermissions = grp.RootPart.EveryoneMask & allowablePermissionsMask;
717 item.GroupPermissions = grp.RootPart.GroupMask & allowablePermissionsMask;
718 }
719 item.CreationDate = Util.UnixTimeSinceEpoch();
720 746
721 // sets itemID so client can show item as 'attached' in inventory 747 // sets itemID so client can show item as 'attached' in inventory
722 grp.FromItemID = item.ID; 748 grp.FromItemID = newItem.ID;
723
724 if (m_scene.AddInventoryItem(item))
725 {
726 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
727 }
728 else
729 {
730 if (m_dialogModule != null)
731 m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed");
732 }
733 749
734 return item; 750 return newItem;
735 } 751 }
736 752
737 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. 753 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so)
738 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
739 private void DetachSingleAttachmentToInvInternal(IScenePresence sp, UUID itemID)
740 { 754 {
741 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); 755 // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
742 756
743 if (itemID == UUID.Zero) // If this happened, someone made a mistake.... 757 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero);
744 return; 758 sp.RemoveAttachment(so);
745
746 // We can NOT use the dictionries here, as we are looking
747 // for an entity by the fromAssetID, which is NOT the prim UUID
748 EntityBase[] detachEntities = m_scene.GetEntities();
749 SceneObjectGroup group;
750
751 lock (sp.AttachmentsSyncLock)
752 {
753 foreach (EntityBase entity in detachEntities)
754 {
755 if (entity is SceneObjectGroup)
756 {
757 group = (SceneObjectGroup)entity;
758 if (group.FromItemID == itemID)
759 {
760 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
761 sp.RemoveAttachment(group);
762 759
763 // Prepare sog for storage 760 // We can only remove the script instances from the script engine after we've retrieved their xml state
764 group.AttachedAvatar = UUID.Zero; 761 // when we update the attachment item.
765 group.RootPart.SetParentLocalId(0); 762 m_scene.DeleteSceneObject(so, false, false);
766 group.IsAttachment = false;
767 group.AbsolutePosition = group.RootPart.AttachedPos;
768 763
769 UpdateKnownItem(sp, group, true); 764 // Prepare sog for storage
770 m_scene.DeleteSceneObject(group, false); 765 so.AttachedAvatar = UUID.Zero;
766 so.RootPart.SetParentLocalId(0);
767 so.IsAttachment = false;
768 so.AbsolutePosition = so.RootPart.AttachedPos;
771 769
772 return; 770 UpdateKnownItem(sp, so, true);
773 } 771 so.RemoveScriptInstances(true);
774 }
775 }
776 }
777 } 772 }
778 773
779 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 774 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
780 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc) 775 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
781 { 776 {
782 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 777 if (m_invAccessModule == null)
783 if (invAccess != null) 778 return null;
779
780 lock (sp.AttachmentsSyncLock)
784 { 781 {
785 lock (sp.AttachmentsSyncLock) 782 SceneObjectGroup objatt;
783
784 if (itemID != UUID.Zero)
785 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
786 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
787 false, false, sp.UUID, true);
788 else
789 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
790 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
791 false, false, sp.UUID, true);
792
793 if (objatt != null)
786 { 794 {
787 SceneObjectGroup objatt; 795// m_log.DebugFormat(
788 796// "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
789 if (itemID != UUID.Zero) 797// objatt.Name, sp.Name, attachmentPt, m_scene.Name);
790 objatt = invAccess.RezObject(sp.ControllingClient, 798
791 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 799 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
792 false, false, sp.UUID, true); 800 objatt.HasGroupChanged = false;
793 else 801 bool tainted = false;
794 objatt = invAccess.RezObject(sp.ControllingClient, 802 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
795 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 803 tainted = true;
796 false, false, sp.UUID, true); 804
797 805 // FIXME: Detect whether it's really likely for AttachObject to throw an exception in the normal
798 // m_log.DebugFormat( 806 // course of events. If not, then it's probably not worth trying to recover the situation
799 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", 807 // since this is more likely to trigger further exceptions and confuse later debugging. If
800 // objatt.Name, remoteClient.Name, AttachmentPt); 808 // exceptions can be thrown in expected error conditions (not NREs) then make this consistent
801 809 // since other normal error conditions will simply return false instead.
802 if (objatt != null) 810 // This will throw if the attachment fails
811 try
803 { 812 {
804 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 813 AttachObject(sp, objatt, attachmentPt, false, false);
805 objatt.HasGroupChanged = false;
806 bool tainted = false;
807 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
808 tainted = true;
809
810 // This will throw if the attachment fails
811 try
812 {
813 AttachObject(sp, objatt, attachmentPt, false, false);
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
819 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
820
821 // Make sure the object doesn't stick around and bail
822 sp.RemoveAttachment(objatt);
823 m_scene.DeleteSceneObject(objatt, false);
824 return null;
825 }
826
827 if (tainted)
828 objatt.HasGroupChanged = true;
829
830 if (doc != null)
831 {
832 objatt.LoadScriptState(doc);
833 objatt.ResetOwnerChangeFlag();
834 }
835
836 // Fire after attach, so we don't get messy perms dialogs
837 // 4 == AttachedRez
838 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
839 objatt.ResumeScripts();
840
841 // Do this last so that event listeners have access to all the effects of the attachment
842 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
843
844 return objatt;
845 } 814 }
846 else 815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
819 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
820
821 // Make sure the object doesn't stick around and bail
822 sp.RemoveAttachment(objatt);
823 m_scene.DeleteSceneObject(objatt, false);
824 return null;
825 }
826
827 if (tainted)
828 objatt.HasGroupChanged = true;
829
830 if (doc != null)
847 { 831 {
848 m_log.WarnFormat( 832 objatt.LoadScriptState(doc);
849 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", 833 objatt.ResetOwnerChangeFlag();
850 itemID, sp.Name, attachmentPt);
851 } 834 }
835
836 // Fire after attach, so we don't get messy perms dialogs
837 // 4 == AttachedRez
838 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
839 objatt.ResumeScripts();
840
841 // Do this last so that event listeners have access to all the effects of the attachment
842 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
843
844 return objatt;
845 }
846 else
847 {
848 m_log.WarnFormat(
849 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
850 itemID, sp.Name, attachmentPt);
852 } 851 }
853 } 852 }
854 853
@@ -864,9 +863,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
864 /// <param name="att"></param> 863 /// <param name="att"></param>
865 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 864 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
866 { 865 {
867 // m_log.DebugFormat( 866// m_log.DebugFormat(
868 // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 867// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
869 // att.Name, sp.Name, AttachmentPt, itemID); 868// att.Name, sp.Name, AttachmentPt, itemID);
870 869
871 if (UUID.Zero == itemID) 870 if (UUID.Zero == itemID)
872 { 871 {
@@ -884,7 +883,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
884 item = m_scene.InventoryService.GetItem(item); 883 item = m_scene.InventoryService.GetItem(item);
885 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 884 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
886 if (changed && m_scene.AvatarFactory != null) 885 if (changed && m_scene.AvatarFactory != null)
886 {
887// m_log.DebugFormat(
888// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
889// sp.Name, att.Name, AttachmentPt);
890
887 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 891 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
892 }
888 } 893 }
889 894
890 #endregion 895 #endregion
@@ -929,9 +934,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
929 934
930 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) 935 private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
931 { 936 {
932 // m_log.DebugFormat( 937// m_log.DebugFormat(
933 // "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})", 938// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
934 // objectLocalID, remoteClient.Name, AttachmentPt, silent); 939// objectLocalID, remoteClient.Name, AttachmentPt, silent);
935 940
936 if (!Enabled) 941 if (!Enabled)
937 return; 942 return;
@@ -967,13 +972,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
967 // Calls attach with a Zero position 972 // Calls attach with a Zero position
968 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true)) 973 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true))
969 { 974 {
970 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 975// m_log.Debug(
976// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
977// + ", AttachmentPoint: " + AttachmentPt);
971 978
972 // Save avatar attachment information 979 // Save avatar attachment information
973 m_log.Debug( 980 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
974 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
975 + ", AttachmentPoint: " + AttachmentPt);
976
977 } 981 }
978 } 982 }
979 catch (Exception e) 983 catch (Exception e)
@@ -989,8 +993,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
989 993
990 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 994 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
991 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 995 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
996
992 if (sp != null && group != null) 997 if (sp != null && group != null)
993 DetachSingleAttachmentToInv(sp, group.FromItemID); 998 DetachSingleAttachmentToInv(sp, group);
994 } 999 }
995 1000
996 private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient) 1001 private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient)
@@ -1000,7 +1005,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1000 1005
1001 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1006 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
1002 if (sp != null) 1007 if (sp != null)
1003 DetachSingleAttachmentToInv(sp, itemID); 1008 {
1009 lock (sp.AttachmentsSyncLock)
1010 {
1011 List<SceneObjectGroup> attachments = sp.GetAttachments();
1012
1013 foreach (SceneObjectGroup group in attachments)
1014 {
1015 if (group.FromItemID == itemID)
1016 {
1017 DetachSingleAttachmentToInv(sp, group);
1018 return;
1019 }
1020 }
1021 }
1022 }
1004 } 1023 }
1005 1024
1006 private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient) 1025 private void Client_OnObjectDrop(uint soLocalId, IClientAPI remoteClient)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 7119ad2..cd1e1c1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Threading; 32using System.Threading;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using Timer=System.Timers.Timer; 35using Timer=System.Timers.Timer;
35using Nini.Config; 36using Nini.Config;
36using NUnit.Framework; 37using NUnit.Framework;
@@ -38,11 +39,16 @@ using OpenMetaverse;
38using OpenSim.Framework; 39using OpenSim.Framework;
39using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
40using OpenSim.Region.CoreModules.Avatar.Attachments; 41using OpenSim.Region.CoreModules.Avatar.Attachments;
42using OpenSim.Region.CoreModules.Framework;
43using OpenSim.Region.CoreModules.Framework.EntityTransfer;
41using OpenSim.Region.CoreModules.Framework.InventoryAccess; 44using OpenSim.Region.CoreModules.Framework.InventoryAccess;
42using OpenSim.Region.CoreModules.World.Serialiser; 45using OpenSim.Region.CoreModules.Scripting.WorldComm;
43using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.XEngine;
51using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common; 52using OpenSim.Tests.Common;
47using OpenSim.Tests.Common.Mock; 53using OpenSim.Tests.Common.Mock;
48 54
@@ -52,11 +58,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
52 /// Attachment tests 58 /// Attachment tests
53 /// </summary> 59 /// </summary>
54 [TestFixture] 60 [TestFixture]
55 public class AttachmentsModuleTests 61 public class AttachmentsModuleTests : OpenSimTestCase
56 { 62 {
57 private Scene scene; 63 private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
58 private AttachmentsModule m_attMod; 64 private OSChatMessage m_osChatMessageReceived;
59 private ScenePresence m_presence;
60 65
61 [TestFixtureSetUp] 66 [TestFixtureSetUp]
62 public void FixtureInit() 67 public void FixtureInit()
@@ -65,52 +70,129 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
65 Util.FireAndForgetMethod = FireAndForgetMethod.None; 70 Util.FireAndForgetMethod = FireAndForgetMethod.None;
66 } 71 }
67 72
68 [SetUp] 73 [TestFixtureTearDown]
69 public void Init() 74 public void TearDown()
75 {
76 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
77 // threads. Possibly, later tests should be rewritten not to worry about such things.
78 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
79 }
80
81 private void OnChatFromWorld(object sender, OSChatMessage oscm)
82 {
83// Console.WriteLine("Got chat [{0}]", oscm.Message);
84
85 m_osChatMessageReceived = oscm;
86 m_chatEvent.Set();
87 }
88
89 private Scene CreateTestScene()
70 { 90 {
71 IConfigSource config = new IniConfigSource(); 91 IConfigSource config = new IniConfigSource();
92 List<object> modules = new List<object>();
93
94 AddCommonConfig(config, modules);
95
96 Scene scene
97 = new SceneHelpers().SetupScene(
98 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
99 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
100
101 return scene;
102 }
103
104 private Scene CreateScriptingEnabledTestScene()
105 {
106 IConfigSource config = new IniConfigSource();
107 List<object> modules = new List<object>();
108
109 AddCommonConfig(config, modules);
110 AddScriptingConfig(config, modules);
111
112 Scene scene
113 = new SceneHelpers().SetupScene(
114 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
115 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
116
117 scene.StartScripts();
118
119 return scene;
120 }
121
122 private void AddCommonConfig(IConfigSource config, List<object> modules)
123 {
72 config.AddConfig("Modules"); 124 config.AddConfig("Modules");
73 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 125 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
74 126
75 scene = SceneHelpers.SetupScene(); 127 modules.Add(new AttachmentsModule());
76 m_attMod = new AttachmentsModule(); 128 modules.Add(new BasicInventoryAccessModule());
77 SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
78 } 129 }
79 130
80 [TestFixtureTearDown] 131 private void AddScriptingConfig(IConfigSource config, List<object> modules)
81 public void TearDown()
82 { 132 {
83 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple 133 IConfig startupConfig = config.AddConfig("Startup");
84 // threads. Possibly, later tests should be rewritten not to worry about such things. 134 startupConfig.Set("DefaultScriptEngine", "XEngine");
85 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; 135
136 IConfig xEngineConfig = config.AddConfig("XEngine");
137 xEngineConfig.Set("Enabled", "true");
138 xEngineConfig.Set("StartDelay", "0");
139
140 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
141 // to AssemblyResolver.OnAssemblyResolve fails.
142 xEngineConfig.Set("AppDomainLoading", "false");
143
144 modules.Add(new XEngine());
145
146 // Necessary to stop serialization complaining
147 // FIXME: Stop this being necessary if at all possible
148// modules.Add(new WorldCommModule());
86 } 149 }
87 150
88 /// <summary> 151 /// <summary>
89 /// Add the standard presence for a test. 152 /// Creates an attachment item in the given user's inventory. Does not attach.
90 /// </summary> 153 /// </summary>
91 private void AddPresence() 154 /// <remarks>
155 /// A user with the given ID and an inventory must already exist.
156 /// </remarks>
157 /// <returns>
158 /// The attachment item.
159 /// </returns>
160 /// <param name='scene'></param>
161 /// <param name='userId'></param>
162 /// <param name='attName'></param>
163 /// <param name='rawItemId'></param>
164 /// <param name='rawAssetId'></param>
165 private InventoryItemBase CreateAttachmentItem(
166 Scene scene, UUID userId, string attName, int rawItemId, int rawAssetId)
92 { 167 {
93 UUID userId = TestHelpers.ParseTail(0x1); 168 return UserInventoryHelpers.CreateInventoryItem(
94 UserAccountHelpers.CreateUserWithInventory(scene, userId); 169 scene,
95 m_presence = SceneHelpers.AddScenePresence(scene, userId); 170 attName,
171 TestHelpers.ParseTail(rawItemId),
172 TestHelpers.ParseTail(rawAssetId),
173 userId,
174 InventoryType.Object);
96 } 175 }
97 176
98 [Test] 177 [Test]
99 public void TestAddAttachmentFromGround() 178 public void TestAddAttachmentFromGround()
100 { 179 {
101 TestHelpers.InMethod(); 180 TestHelpers.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 181// TestHelpers.EnableLogging();
182
183 Scene scene = CreateTestScene();
184 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
185 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
103 186
104 AddPresence();
105 string attName = "att"; 187 string attName = "att";
106 188
107 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup; 189 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
108 190
109 m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false, false); 191 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
110 192
111 // Check status on scene presence 193 // Check status on scene presence
112 Assert.That(m_presence.HasAttachments(), Is.True); 194 Assert.That(sp.HasAttachments(), Is.True);
113 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 195 List<SceneObjectGroup> attachments = sp.GetAttachments();
114 Assert.That(attachments.Count, Is.EqualTo(1)); 196 Assert.That(attachments.Count, Is.EqualTo(1));
115 SceneObjectGroup attSo = attachments[0]; 197 SceneObjectGroup attSo = attachments[0];
116 Assert.That(attSo.Name, Is.EqualTo(attName)); 198 Assert.That(attSo.Name, Is.EqualTo(attName));
@@ -121,42 +203,107 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
121 203
122 // Check item status 204 // Check item status
123 Assert.That( 205 Assert.That(
124 m_presence.Appearance.GetAttachpoint(attSo.FromItemID), 206 sp.Appearance.GetAttachpoint(attSo.FromItemID),
125 Is.EqualTo((int)AttachmentPoint.Chest)); 207 Is.EqualTo((int)AttachmentPoint.Chest));
208
209 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID));
210 Assert.That(attachmentItem, Is.Not.Null);
211 Assert.That(attachmentItem.Name, Is.EqualTo(attName));
212
213 InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object);
214 Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID));
215
216 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
217
218// TestHelpers.DisableLogging();
126 } 219 }
127 220
221 /// <summary>
222 /// Test that we do not attempt to attach an in-world object that someone else is sitting on.
223 /// </summary>
128 [Test] 224 [Test]
129 public void TestAddAttachmentFromInventory() 225 public void TestAddSatOnAttachmentFromGround()
130 { 226 {
131 TestHelpers.InMethod(); 227 TestHelpers.InMethod();
132// log4net.Config.XmlConfigurator.Configure(); 228// TestHelpers.EnableLogging();
133 229
134 AddPresence(); 230 Scene scene = CreateTestScene();
231 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
232 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
135 233
136 UUID attItemId = TestHelpers.ParseTail(0x2);
137 UUID attAssetId = TestHelpers.ParseTail(0x3);
138 string attName = "att"; 234 string attName = "att";
139 235
140 UserInventoryHelpers.CreateInventoryItem( 236 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
141 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 237
238 UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2);
239 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2);
240
241 // Put avatar within 10m of the prim so that sit doesn't fail.
242 sp2.AbsolutePosition = new Vector3(0, 0, 0);
243 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
244
245 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
246
247 Assert.That(sp.HasAttachments(), Is.False);
248 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
249 }
250
251 [Test]
252 public void TestRezAttachmentFromInventory()
253 {
254 TestHelpers.InMethod();
255// log4net.Config.XmlConfigurator.Configure();
256
257 Scene scene = CreateTestScene();
258 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
259 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
142 260
143 m_attMod.RezSingleAttachmentFromInventory( 261 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
144 m_presence, attItemId, (uint)AttachmentPoint.Chest); 262
263 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
264 sp, attItem.ID, (uint)AttachmentPoint.Chest);
145 265
146 // Check scene presence status 266 // Check scene presence status
147 Assert.That(m_presence.HasAttachments(), Is.True); 267 Assert.That(sp.HasAttachments(), Is.True);
148 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 268 List<SceneObjectGroup> attachments = sp.GetAttachments();
149 Assert.That(attachments.Count, Is.EqualTo(1)); 269 Assert.That(attachments.Count, Is.EqualTo(1));
150 SceneObjectGroup attSo = attachments[0]; 270 SceneObjectGroup attSo = attachments[0];
151 Assert.That(attSo.Name, Is.EqualTo(attName)); 271 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
152 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 272 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
153 Assert.That(attSo.IsAttachment); 273 Assert.That(attSo.IsAttachment);
154 Assert.That(attSo.UsesPhysics, Is.False); 274 Assert.That(attSo.UsesPhysics, Is.False);
155 Assert.That(attSo.IsTemporary, Is.False); 275 Assert.That(attSo.IsTemporary, Is.False);
156 276
157 // Check appearance status 277 // Check appearance status
158 Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1)); 278 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
159 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); 279 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
280
281 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
282 }
283
284 /// <summary>
285 /// Test specific conditions associated with rezzing a scripted attachment from inventory.
286 /// </summary>
287 [Test]
288 public void TestRezScriptedAttachmentFromInventory()
289 {
290 TestHelpers.InMethod();
291
292 Scene scene = CreateTestScene();
293 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
294 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
295
296 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
297 TaskInventoryHelpers.AddScript(scene, so.RootPart);
298 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
299
300 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
301
302 // TODO: Need to have a test that checks the script is actually started but this involves a lot more
303 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various
304 // script engine delays/asychronicity that isn't helpful in an automated regression testing context.
305 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
306 Assert.That(attSo.ContainsScripts(), Is.True);
160 } 307 }
161 308
162 [Test] 309 [Test]
@@ -165,29 +312,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
165 TestHelpers.InMethod(); 312 TestHelpers.InMethod();
166// log4net.Config.XmlConfigurator.Configure(); 313// log4net.Config.XmlConfigurator.Configure();
167 314
168 AddPresence(); 315 Scene scene = CreateTestScene();
316 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
317 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
169 318
170 UUID attItemId = TestHelpers.ParseTail(0x2); 319 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
171 UUID attAssetId = TestHelpers.ParseTail(0x3);
172 string attName = "att";
173 320
174 UserInventoryHelpers.CreateInventoryItem( 321 ISceneEntity so
175 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object); 322 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
176 323 sp, attItem.ID, (uint)AttachmentPoint.Chest);
177 ISceneEntity so = m_attMod.RezSingleAttachmentFromInventory( 324 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
178 m_presence, attItemId, (uint)AttachmentPoint.Chest);
179 m_attMod.DetachSingleAttachmentToGround(m_presence, so.LocalId);
180 325
181 // Check scene presence status 326 // Check scene presence status
182 Assert.That(m_presence.HasAttachments(), Is.False); 327 Assert.That(sp.HasAttachments(), Is.False);
183 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 328 List<SceneObjectGroup> attachments = sp.GetAttachments();
184 Assert.That(attachments.Count, Is.EqualTo(0)); 329 Assert.That(attachments.Count, Is.EqualTo(0));
185 330
186 // Check appearance status 331 // Check appearance status
187 Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(0)); 332 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
188 333
189 // Check item status 334 // Check item status
190 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItemId)), Is.Null); 335 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null);
191 336
192 // Check object in scene 337 // Check object in scene
193 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 338 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
@@ -197,28 +342,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 public void TestDetachAttachmentToInventory() 342 public void TestDetachAttachmentToInventory()
198 { 343 {
199 TestHelpers.InMethod(); 344 TestHelpers.InMethod();
200// log4net.Config.XmlConfigurator.Configure();
201 345
202 AddPresence(); 346 Scene scene = CreateTestScene();
347 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
348 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID);
203 349
204 UUID attItemId = TestHelpers.ParseTail(0x2); 350 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
205 UUID attAssetId = TestHelpers.ParseTail(0x3);
206 string attName = "att";
207
208 UserInventoryHelpers.CreateInventoryItem(
209 scene, attName, attItemId, attAssetId, m_presence.UUID, InventoryType.Object);
210 351
211 m_attMod.RezSingleAttachmentFromInventory( 352 SceneObjectGroup so
212 m_presence, attItemId, (uint)AttachmentPoint.Chest); 353 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
213 m_attMod.DetachSingleAttachmentToInv(m_presence, attItemId); 354 sp, attItem.ID, (uint)AttachmentPoint.Chest);
355 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
214 356
215 // Check status on scene presence 357 // Check status on scene presence
216 Assert.That(m_presence.HasAttachments(), Is.False); 358 Assert.That(sp.HasAttachments(), Is.False);
217 List<SceneObjectGroup> attachments = m_presence.GetAttachments(); 359 List<SceneObjectGroup> attachments = sp.GetAttachments();
218 Assert.That(attachments.Count, Is.EqualTo(0)); 360 Assert.That(attachments.Count, Is.EqualTo(0));
219 361
220 // Check item status 362 // Check item status
221 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); 363 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
364
365 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
366 }
367
368 /// <summary>
369 /// Test specific conditions associated with detaching a scripted attachment from inventory.
370 /// </summary>
371 [Test]
372 public void TestDetachScriptedAttachmentToInventory()
373 {
374 TestHelpers.InMethod();
375// TestHelpers.EnableLogging();
376
377 Scene scene = CreateScriptingEnabledTestScene();
378 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
379 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
380
381 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
382 TaskInventoryHelpers.AddScript(scene, so.RootPart);
383 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
384
385 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
386 // In the future, we need to be able to do this programatically more predicably.
387 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
388
389 SceneObjectGroup soRezzed
390 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
391
392 // Wait for chat to signal rezzed script has been started.
393 m_chatEvent.WaitOne(60000);
394
395 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed);
396
397 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
398 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
399
400 XmlDocument soXml = new XmlDocument();
401 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
402
403 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
404 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
222 } 405 }
223 406
224 /// <summary> 407 /// <summary>
@@ -230,17 +413,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
230 TestHelpers.InMethod(); 413 TestHelpers.InMethod();
231// log4net.Config.XmlConfigurator.Configure(); 414// log4net.Config.XmlConfigurator.Configure();
232 415
233 UUID userId = TestHelpers.ParseTail(0x1); 416 Scene scene = CreateTestScene();
234 UUID attItemId = TestHelpers.ParseTail(0x2); 417 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
235 UUID attAssetId = TestHelpers.ParseTail(0x3); 418 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
236 string attName = "att";
237
238 UserAccountHelpers.CreateUserWithInventory(scene, userId);
239 InventoryItemBase attItem
240 = UserInventoryHelpers.CreateInventoryItem(
241 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
242 419
243 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 420 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
244 acd.Appearance = new AvatarAppearance(); 421 acd.Appearance = new AvatarAppearance();
245 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 422 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
246 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 423 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -259,17 +436,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
259 TestHelpers.InMethod(); 436 TestHelpers.InMethod();
260// log4net.Config.XmlConfigurator.Configure(); 437// log4net.Config.XmlConfigurator.Configure();
261 438
262 UUID userId = TestHelpers.ParseTail(0x1); 439 Scene scene = CreateTestScene();
263 UUID attItemId = TestHelpers.ParseTail(0x2); 440 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
264 UUID attAssetId = TestHelpers.ParseTail(0x3); 441 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
265 string attName = "att";
266 442
267 UserAccountHelpers.CreateUserWithInventory(scene, userId); 443 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
268 InventoryItemBase attItem
269 = UserInventoryHelpers.CreateInventoryItem(
270 scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
271
272 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
273 acd.Appearance = new AvatarAppearance(); 444 acd.Appearance = new AvatarAppearance();
274 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 445 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
275 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 446 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
@@ -279,7 +450,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
279 450
280 Assert.That(attachments.Count, Is.EqualTo(1)); 451 Assert.That(attachments.Count, Is.EqualTo(1));
281 SceneObjectGroup attSo = attachments[0]; 452 SceneObjectGroup attSo = attachments[0];
282 Assert.That(attSo.Name, Is.EqualTo(attName)); 453 Assert.That(attSo.Name, Is.EqualTo(attItem.Name));
283 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); 454 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
284 Assert.That(attSo.IsAttachment); 455 Assert.That(attSo.IsAttachment);
285 Assert.That(attSo.UsesPhysics, Is.False); 456 Assert.That(attSo.UsesPhysics, Is.False);
@@ -289,9 +460,125 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
289 List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments(); 460 List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
290 Assert.That(retreivedAttachments.Count, Is.EqualTo(1)); 461 Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
291 Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); 462 Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
292 Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId)); 463 Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID));
293 Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId)); 464 Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
294 Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); 465 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
466
467 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
468 }
469
470 [Test]
471 public void TestUpdateAttachmentPosition()
472 {
473 TestHelpers.InMethod();
474
475 Scene scene = CreateTestScene();
476 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
477 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
478
479 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
480 acd.Appearance = new AvatarAppearance();
481 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
482 ScenePresence sp = SceneHelpers.AddScenePresence(scene, acd);
483
484 SceneObjectGroup attSo = sp.GetAttachments()[0];
485
486 Vector3 newPosition = new Vector3(1, 2, 4);
487
488 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
489
490 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
491 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
492 }
493
494 [Test]
495 public void TestSameSimulatorNeighbouringRegionsTeleport()
496 {
497 TestHelpers.InMethod();
498// TestHelpers.EnableLogging();
499
500 AttachmentsModule attModA = new AttachmentsModule();
501 AttachmentsModule attModB = new AttachmentsModule();
502 EntityTransferModule etmA = new EntityTransferModule();
503 EntityTransferModule etmB = new EntityTransferModule();
504 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
505
506 IConfigSource config = new IniConfigSource();
507 IConfig modulesConfig = config.AddConfig("Modules");
508 modulesConfig.Set("EntityTransferModule", etmA.Name);
509 modulesConfig.Set("SimulationServices", lscm.Name);
510 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
511
512 // In order to run a single threaded regression test we do not want the entity transfer module waiting
513 // for a callback from the destination scene before removing its avatar data.
514 entityTransferConfig.Set("wait_for_callback", false);
515
516 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
517
518 SceneHelpers sh = new SceneHelpers();
519 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
520 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
521
522 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
523 SceneHelpers.SetupSceneModules(
524 sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
525 SceneHelpers.SetupSceneModules(
526 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
527
528 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
529 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager);
530 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
531
532 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
533
534 sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
535 beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
536
537 Vector3 teleportPosition = new Vector3(10, 11, 12);
538 Vector3 teleportLookAt = new Vector3(20, 21, 22);
539
540 sceneA.RequestTeleportLocation(
541 beforeTeleportSp.ControllingClient,
542 sceneB.RegionInfo.RegionHandle,
543 teleportPosition,
544 teleportLookAt,
545 (uint)TeleportFlags.ViaLocation);
546
547 ((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide();
548
549 // Check attachments have made it into sceneB
550 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
551
552 // This is appearance data, as opposed to actually rezzed attachments
553 List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
554 Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
555 Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
556 Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
557 Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
558 Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
559
560 // This is the actual attachment
561 List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
562 Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
563 SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
564 Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
565 Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
566
567 Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
568
569 // Check attachments have been removed from sceneA
570 ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
571
572 // Since this is appearance data, it is still present on the child avatar!
573 List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
574 Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
575 Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
576
577 // This is the actual attachment, which should no longer exist
578 List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
579 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
580
581 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
295 } 582 }
296 583
297 // I'm commenting this test because scene setup NEEDS InventoryService to 584 // I'm commenting this test because scene setup NEEDS InventoryService to
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 2bebd30..89cc4f6 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -128,7 +128,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
128 /// <param name="visualParam"></param> 128 /// <param name="visualParam"></param>
129 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) 129 public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams)
130 { 130 {
131 // m_log.InfoFormat("[AVFACTORY]: start SetAppearance for {0}", client.AgentId); 131// m_log.DebugFormat(
132// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}",
133// sp.Name, textureEntry, visualParams);
132 134
133 // TODO: This is probably not necessary any longer, just assume the 135 // TODO: This is probably not necessary any longer, just assume the
134 // textureEntry set implies that the appearance transaction is complete 136 // textureEntry set implies that the appearance transaction is complete
@@ -158,7 +160,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
158 // Process the baked texture array 160 // Process the baked texture array
159 if (textureEntry != null) 161 if (textureEntry != null)
160 { 162 {
161 m_log.InfoFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); 163// m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID);
162 164
163// WriteBakedTexturesReport(sp, m_log.DebugFormat); 165// WriteBakedTexturesReport(sp, m_log.DebugFormat);
164 166
@@ -208,7 +210,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
208 ScenePresence sp = m_scene.GetScenePresence(agentId); 210 ScenePresence sp = m_scene.GetScenePresence(agentId);
209 if (sp == null) 211 if (sp == null)
210 { 212 {
211 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); 213 // This is expected if the user has gone away.
214// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId);
212 return false; 215 return false;
213 } 216 }
214 217
@@ -248,10 +251,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
248 251
249 if (bakedTextureFace == null) 252 if (bakedTextureFace == null)
250 { 253 {
251 m_log.WarnFormat( 254 // This can happen legitimately, since some baked textures might not exist
252 "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently", 255 //m_log.WarnFormat(
253 bakeType, sp.Name, m_scene.RegionInfo.RegionName); 256 // "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
254 257 // bakeType, sp.Name, m_scene.RegionInfo.RegionName);
255 continue; 258 continue;
256 } 259 }
257 260
@@ -337,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
337 return false; 340 return false;
338 } 341 }
339 342
340 m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 343// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID);
341 344
342 // If we only found default textures, then the appearance is not cached 345 // If we only found default textures, then the appearance is not cached
343 return (defonly ? false : true); 346 return (defonly ? false : true);
@@ -370,11 +373,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
370 if (missingTexturesOnly) 373 if (missingTexturesOnly)
371 { 374 {
372 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 375 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null)
376 {
373 continue; 377 continue;
378 }
374 else 379 else
380 {
381 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
382 // grid asset service (which means that they are not available to the new region and so have
383 // to be re-requested from the client).
384 //
385 // The only available core OpenSimulator behaviour right now
386 // is not to store these textures, temporarily or otherwise.
375 m_log.DebugFormat( 387 m_log.DebugFormat(
376 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 388 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
377 face.TextureID, idx, sp.Name); 389 face.TextureID, idx, sp.Name);
390 }
378 } 391 }
379 else 392 else
380 { 393 {
@@ -417,7 +430,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
417// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 430// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
418 431
419 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); 432 int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType);
420 bakedTextures[bakeType] = faceTextures[ftIndex]; 433 Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture
434 bakedTextures[bakeType] = texture;
421 } 435 }
422 436
423 return bakedTextures; 437 return bakedTextures;
@@ -482,7 +496,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
482 ScenePresence sp = m_scene.GetScenePresence(agentid); 496 ScenePresence sp = m_scene.GetScenePresence(agentid);
483 if (sp == null) 497 if (sp == null)
484 { 498 {
485 m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); 499 // This is expected if the user has gone away.
500// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid);
486 return; 501 return;
487 } 502 }
488 503
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 11a0a86..848b3bf 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
53 UUID userId = TestHelpers.ParseTail(0x1); 53 UUID userId = TestHelpers.ParseTail(0x1);
54 54
55 AvatarFactoryModule afm = new AvatarFactoryModule(); 55 AvatarFactoryModule afm = new AvatarFactoryModule();
56 TestScene scene = SceneHelpers.SetupScene(); 56 TestScene scene = new SceneHelpers().SetupScene();
57 SceneHelpers.SetupSceneModules(scene, afm); 57 SceneHelpers.SetupSceneModules(scene, afm);
58 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 58 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
59 59
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
81 CoreAssetCache assetCache = new CoreAssetCache(); 81 CoreAssetCache assetCache = new CoreAssetCache();
82 82
83 AvatarFactoryModule afm = new AvatarFactoryModule(); 83 AvatarFactoryModule afm = new AvatarFactoryModule();
84 TestScene scene = SceneHelpers.SetupScene(assetCache); 84 TestScene scene = new SceneHelpers(assetCache).SetupScene();
85 SceneHelpers.SetupSceneModules(scene, afm); 85 SceneHelpers.SetupSceneModules(scene, afm);
86 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 86 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
87 87
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 6215526..dbbb0ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -266,7 +266,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
266 receiverIDs.Add(presence.UUID); 266 receiverIDs.Add(presence.UUID);
267 } 267 }
268 } 268 }
269
270 } 269 }
271 ); 270 );
272 } 271 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 0babeb5..3a91465 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -96,6 +96,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
96 ScenePresence killingAvatar = null; 96 ScenePresence killingAvatar = null;
97// string killingAvatarMessage; 97// string killingAvatarMessage;
98 98
99 // check to see if it is an NPC and just remove it
100 INPCModule NPCmodule = deadAvatar.Scene.RequestModuleInterface<INPCModule>();
101 if (NPCmodule != null && NPCmodule.DeleteNPC(deadAvatar.UUID, deadAvatar.Scene))
102 {
103 return;
104 }
105
99 if (killerObjectLocalID == 0) 106 if (killerObjectLocalID == 0)
100 deadAvatarMessage = "You committed suicide!"; 107 deadAvatarMessage = "You committed suicide!";
101 else 108 else
@@ -145,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
145 catch (InvalidOperationException) 152 catch (InvalidOperationException)
146 { } 153 { }
147 154
148 deadAvatar.Health = 100; 155 deadAvatar.setHealthWithUpdate(100.0f);
149 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient); 156 deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient);
150 } 157 }
151 158
@@ -154,14 +161,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
154 try 161 try
155 { 162 {
156 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 163 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
157 164 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
158 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) 165 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
159 { 166 {
160 avatar.Invulnerable = false; 167 avatar.Invulnerable = false;
161 } 168 }
162 else 169 else
163 { 170 {
164 avatar.Invulnerable = true; 171 avatar.Invulnerable = true;
172 if (avatar.Health < 100.0f)
173 {
174 avatar.setHealthWithUpdate(100.0f);
175 }
165 } 176 }
166 } 177 }
167 catch (Exception) 178 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
new file mode 100644
index 0000000..4bcd2ac
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -0,0 +1,189 @@
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.Reflection;
31using System.Text;
32using System.Text.RegularExpressions;
33using log4net;
34using Mono.Addins;
35using NDesk.Options;
36using Nini.Config;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.CoreModules.Avatars.Commands
45{
46 /// <summary>
47 /// A module that holds commands for manipulating objects in the scene.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserCommandsModule")]
50 public class UserCommandsModule : ISharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 public const string TeleportUserCommandSyntax = "teleport user <first-name> <last-name> <destination>";
55
56 public static Regex InterRegionDestinationRegex
57 = new Regex(@"^(?<regionName>.+)/(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
58
59 public static Regex WithinRegionDestinationRegex
60 = new Regex(@"^(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
61
62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
63
64 public string Name { get { return "User Commands Module"; } }
65
66 public Type ReplaceableInterface { get { return null; } }
67
68 public void Initialise(IConfigSource source)
69 {
70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
71 }
72
73 public void PostInitialise()
74 {
75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
76 }
77
78 public void Close()
79 {
80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
81 }
82
83 public void AddRegion(Scene scene)
84 {
85// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
86
87 lock (m_scenes)
88 m_scenes[scene.RegionInfo.RegionID] = scene;
89
90 scene.AddCommand(
91 "Users",
92 this,
93 "teleport user",
94 TeleportUserCommandSyntax,
95 "Teleport a user in this simulator to the given destination",
96 "<destination> is in format [<region-name>]/<x>/<y>/<z>, e.g. regionone/20/30/40 or just 20/30/40 to teleport within same region."
97 + "\nIf the region contains a space then the whole destination must be in quotes, e.g. \"region one/20/30/40\"",
98 HandleTeleportUser);
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
104
105 lock (m_scenes)
106 m_scenes.Remove(scene.RegionInfo.RegionID);
107 }
108
109 public void RegionLoaded(Scene scene)
110 {
111// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
112 }
113
114 private ScenePresence GetUser(string firstName, string lastName)
115 {
116 ScenePresence userFound = null;
117
118 lock (m_scenes)
119 {
120 foreach (Scene scene in m_scenes.Values)
121 {
122 ScenePresence user = scene.GetScenePresence(firstName, lastName);
123 if (user != null && !user.IsChildAgent)
124 {
125 userFound = user;
126 break;
127 }
128 }
129 }
130
131 return userFound;
132 }
133
134 private void HandleTeleportUser(string module, string[] cmd)
135 {
136 if (cmd.Length < 5)
137 {
138 MainConsole.Instance.OutputFormat("Usage: " + TeleportUserCommandSyntax);
139 return;
140 }
141
142 string firstName = cmd[2];
143 string lastName = cmd[3];
144 string rawDestination = cmd[4];
145
146 ScenePresence user = GetUser(firstName, lastName);
147
148 if (user == null)
149 {
150 MainConsole.Instance.OutputFormat("No user found with name {0} {1}", firstName, lastName);
151 return;
152 }
153
154// MainConsole.Instance.OutputFormat("rawDestination [{0}]", rawDestination);
155
156 Match m = WithinRegionDestinationRegex.Match(rawDestination);
157
158 if (!m.Success)
159 {
160 m = InterRegionDestinationRegex.Match(rawDestination);
161
162 if (!m.Success)
163 {
164 MainConsole.Instance.OutputFormat("Invalid destination {0}", rawDestination);
165 return;
166 }
167 }
168
169 string regionName
170 = m.Groups["regionName"].Success ? m.Groups["regionName"].Value : user.Scene.RegionInfo.RegionName;
171
172 MainConsole.Instance.OutputFormat(
173 "Teleporting {0} to {1},{2},{3} in {4}",
174 user.Name,
175 m.Groups["x"], m.Groups["y"], m.Groups["z"],
176 regionName);
177
178 user.Scene.RequestTeleportLocation(
179 user.ControllingClient,
180 regionName,
181 new Vector3(
182 float.Parse(m.Groups["x"].Value),
183 float.Parse(m.Groups["y"].Value),
184 float.Parse(m.Groups["z"].Value)),
185 user.Lookat,
186 (uint)TeleportFlags.ViaLocation);
187 }
188 }
189} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index f64c161..24ec435 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
162 } 162 }
163 } 163 }
164 164
165 protected void InitModule(IConfigSource config) 165 protected virtual void InitModule(IConfigSource config)
166 { 166 {
167 IConfig friendsConfig = config.Configs["Friends"]; 167 IConfig friendsConfig = config.Configs["Friends"];
168 if (friendsConfig != null) 168 if (friendsConfig != null)
@@ -449,29 +449,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
449 /// </summary> 449 /// </summary>
450 public IClientAPI LocateClientObject(UUID agentID) 450 public IClientAPI LocateClientObject(UUID agentID)
451 { 451 {
452 Scene scene = GetClientScene(agentID);
453 if (scene != null)
454 {
455 ScenePresence presence = scene.GetScenePresence(agentID);
456 if (presence != null)
457 return presence.ControllingClient;
458 }
459
460 return null;
461 }
462
463 /// <summary>
464 /// Find the scene for an agent
465 /// </summary>
466 private Scene GetClientScene(UUID agentId)
467 {
468 lock (m_Scenes) 452 lock (m_Scenes)
469 { 453 {
470 foreach (Scene scene in m_Scenes) 454 foreach (Scene scene in m_Scenes)
471 { 455 {
472 ScenePresence presence = scene.GetScenePresence(agentId); 456 ScenePresence presence = scene.GetScenePresence(agentID);
473 if (presence != null && !presence.IsChildAgent) 457 if (presence != null && !presence.IsChildAgent)
474 return scene; 458 return presence.ControllingClient;
475 } 459 }
476 } 460 }
477 461
@@ -498,7 +482,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
498 Util.FireAndForget( 482 Util.FireAndForget(
499 delegate 483 delegate
500 { 484 {
501 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count); 485 m_log.DebugFormat(
486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
487 friendList.Count, agentID, online);
488
502 // Notify about this user status 489 // Notify about this user status
503 StatusNotify(friendList, agentID, online); 490 StatusNotify(friendList, agentID, online);
504 } 491 }
@@ -515,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
515 { 502 {
516 // Try local 503 // Try local
517 if (LocalStatusNotification(userID, friendID, online)) 504 if (LocalStatusNotification(userID, friendID, online))
518 return; 505 continue;
519 506
520 // The friend is not here [as root]. Let's forward. 507 // The friend is not here [as root]. Let's forward.
521 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); 508 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
@@ -523,11 +510,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 { 510 {
524 PresenceInfo friendSession = null; 511 PresenceInfo friendSession = null;
525 foreach (PresenceInfo pinfo in friendSessions) 512 foreach (PresenceInfo pinfo in friendSessions)
513 {
526 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 514 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
527 { 515 {
528 friendSession = pinfo; 516 friendSession = pinfo;
529 break; 517 break;
530 } 518 }
519 }
531 520
532 if (friendSession != null) 521 if (friendSession != null)
533 { 522 {
@@ -546,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
546 } 535 }
547 } 536 }
548 537
549 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 538 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
550 { 539 {
551 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) 540 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
552 { 541 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 9a6d277..06f27e2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
50 { 50 {
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 52
53 private int m_levelHGFriends = 0;
54
53 IUserManagement m_uMan; 55 IUserManagement m_uMan;
54 public IUserManagement UserManagementModule 56 public IUserManagement UserManagementModule
55 { 57 {
@@ -87,6 +89,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
87 m_StatusNotifier = new HGStatusNotifier(this); 89 m_StatusNotifier = new HGStatusNotifier(this);
88 } 90 }
89 91
92 protected override void InitModule(IConfigSource config)
93 {
94 base.InitModule(config);
95
96 // Additionally to the base method
97 IConfig friendsConfig = config.Configs["HGFriendsModule"];
98 if (friendsConfig != null)
99 {
100 m_levelHGFriends = friendsConfig.GetInt("LevelHGFriends", 0);
101
102 // TODO: read in all config variables pertaining to
103 // HG friendship permissions
104 }
105 }
106
90 #endregion 107 #endregion
91 108
92 #region IFriendsSimConnector 109 #region IFriendsSimConnector
@@ -105,6 +122,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
105 122
106 #endregion 123 #endregion
107 124
125 protected override void OnInstantMessage(IClientAPI client, GridInstantMessage im)
126 {
127 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
128 {
129 // we got a friendship offer
130 UUID principalID = new UUID(im.fromAgentID);
131 UUID friendID = new UUID(im.toAgentID);
132
133 // Check if friendID is foreigner and if principalID has the permission
134 // to request friendships with foreigners. If not, return immediately.
135 if (!UserManagementModule.IsLocalGridUser(friendID))
136 {
137 ScenePresence avatar = null;
138 ((Scene)client.Scene).TryGetScenePresence(principalID, out avatar);
139
140 if (avatar == null)
141 return;
142
143 if (avatar.UserLevel < m_levelHGFriends)
144 {
145 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
146 return;
147 }
148 }
149 }
150
151 base.OnInstantMessage(client, im);
152 }
153
108 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders) 154 protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List<UUID> callingCardFolders)
109 { 155 {
110 // Update the local cache. Yes, we need to do it right here 156 // Update the local cache. Yes, we need to do it right here
@@ -369,12 +415,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
369 415
370 protected override void StoreBackwards(UUID friendID, UUID agentID) 416 protected override void StoreBackwards(UUID friendID, UUID agentID)
371 { 417 {
372 Boolean agentIsLocal = true; 418 bool agentIsLocal = true;
373 Boolean friendIsLocal = true; 419// bool friendIsLocal = true;
420
374 if (UserManagementModule != null) 421 if (UserManagementModule != null)
375 { 422 {
376 agentIsLocal = UserManagementModule.IsLocalGridUser(agentID); 423 agentIsLocal = UserManagementModule.IsLocalGridUser(agentID);
377 friendIsLocal = UserManagementModule.IsLocalGridUser(friendID); 424// friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
378 } 425 }
379 426
380 // Is the requester a local user? 427 // Is the requester a local user?
@@ -461,7 +508,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
461 { 508 {
462 friendUUI = finfo.Friend; 509 friendUUI = finfo.Friend;
463 theFriendUUID = friendUUI; 510 theFriendUUID = friendUUI;
464 UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty; 511 UUID utmp = UUID.Zero;
512 string url = String.Empty;
513 string first = String.Empty;
514 string last = String.Empty;
515
465 // If it's confirming the friendship, we already have the full UUI with the secret 516 // If it's confirming the friendship, we already have the full UUI with the secret
466 if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret)) 517 if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
467 { 518 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 45b4264..7a197f7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
78 config.AddConfig("FriendsService"); 78 config.AddConfig("FriendsService");
79 config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 79 config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
80 80
81 m_scene = SceneHelpers.SetupScene(); 81 m_scene = new SceneHelpers().SetupScene();
82 m_fm = new FriendsModule(); 82 m_fm = new FriendsModule();
83 SceneHelpers.SetupSceneModules(m_scene, config, m_fm); 83 SceneHelpers.SetupSceneModules(m_scene, config, m_fm);
84 } 84 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 8560c73..6587ead 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -39,6 +39,9 @@ using OpenSim.Framework.Serialization.External;
39using OpenSim.Region.CoreModules.World.Archiver; 39using OpenSim.Region.CoreModules.World.Archiver;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using Ionic.Zlib;
43using GZipStream = Ionic.Zlib.GZipStream;
44using CompressionMode = Ionic.Zlib.CompressionMode;
42 45
43namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver 46namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
44{ 47{
@@ -91,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 /// Constructor 94 /// Constructor
92 /// </summary> 95 /// </summary>
93 public InventoryArchiveWriteRequest( 96 public InventoryArchiveWriteRequest(
94 Guid id, InventoryArchiverModule module, Scene scene, 97 Guid id, InventoryArchiverModule module, Scene scene,
95 UserAccount userInfo, string invPath, string savePath) 98 UserAccount userInfo, string invPath, string savePath)
96 : this( 99 : this(
97 id, 100 id,
@@ -99,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
99 scene, 102 scene,
100 userInfo, 103 userInfo,
101 invPath, 104 invPath,
102 new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress)) 105 new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression))
103 { 106 {
104 } 107 }
105 108
@@ -107,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
107 /// Constructor 110 /// Constructor
108 /// </summary> 111 /// </summary>
109 public InventoryArchiveWriteRequest( 112 public InventoryArchiveWriteRequest(
110 Guid id, InventoryArchiverModule module, Scene scene, 113 Guid id, InventoryArchiverModule module, Scene scene,
111 UserAccount userInfo, string invPath, Stream saveStream) 114 UserAccount userInfo, string invPath, Stream saveStream)
112 { 115 {
113 m_id = id; 116 m_id = id;
@@ -125,7 +128,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
125 { 128 {
126 Exception reportedException = null; 129 Exception reportedException = null;
127 bool succeeded = true; 130 bool succeeded = true;
128 131
129 try 132 try
130 { 133 {
131 m_archiveWriter.Close(); 134 m_archiveWriter.Close();
@@ -146,6 +149,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
146 149
147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) 150 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService)
148 { 151 {
152 if (options.ContainsKey("exclude"))
153 {
154 if (((List<String>)options["exclude"]).Contains(inventoryItem.Name) ||
155 ((List<String>)options["exclude"]).Contains(inventoryItem.ID.ToString()))
156 {
157 if (options.ContainsKey("verbose"))
158 {
159 m_log.InfoFormat(
160 "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}",
161 inventoryItem.Name, inventoryItem.ID, path);
162 }
163 return;
164 }
165 }
166
149 if (options.ContainsKey("verbose")) 167 if (options.ContainsKey("verbose"))
150 m_log.InfoFormat( 168 m_log.InfoFormat(
151 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
@@ -175,9 +193,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
175 /// <param name="options"></param> 193 /// <param name="options"></param>
176 /// <param name="userAccountService"></param> 194 /// <param name="userAccountService"></param>
177 protected void SaveInvFolder( 195 protected void SaveInvFolder(
178 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself, 196 InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself,
179 Dictionary<string, object> options, IUserAccountService userAccountService) 197 Dictionary<string, object> options, IUserAccountService userAccountService)
180 { 198 {
199 if (options.ContainsKey("excludefolders"))
200 {
201 if (((List<String>)options["excludefolders"]).Contains(inventoryFolder.Name) ||
202 ((List<String>)options["excludefolders"]).Contains(inventoryFolder.ID.ToString()))
203 {
204 if (options.ContainsKey("verbose"))
205 {
206 m_log.InfoFormat(
207 "[INVENTORY ARCHIVER]: Skipping folder {0} at {1}",
208 inventoryFolder.Name, path);
209 }
210 return;
211 }
212 }
213
214 if (options.ContainsKey("verbose"))
215 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving folder {0}", inventoryFolder.Name);
216
181 if (saveThisFolderItself) 217 if (saveThisFolderItself)
182 { 218 {
183 path += CreateArchiveFolderName(inventoryFolder); 219 path += CreateArchiveFolderName(inventoryFolder);
@@ -186,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
186 m_archiveWriter.WriteDir(path); 222 m_archiveWriter.WriteDir(path);
187 } 223 }
188 224
189 InventoryCollection contents 225 InventoryCollection contents
190 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID); 226 = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID);
191 227
192 foreach (InventoryFolderBase childFolder in contents.Folders) 228 foreach (InventoryFolderBase childFolder in contents.Folders)
@@ -213,16 +249,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
213 InventoryFolderBase inventoryFolder = null; 249 InventoryFolderBase inventoryFolder = null;
214 InventoryItemBase inventoryItem = null; 250 InventoryItemBase inventoryItem = null;
215 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); 251 InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);
216 252
217 bool saveFolderContentsOnly = false; 253 bool saveFolderContentsOnly = false;
218 254
219 // Eliminate double slashes and any leading / on the path. 255 // Eliminate double slashes and any leading / on the path.
220 string[] components 256 string[] components
221 = m_invPath.Split( 257 = m_invPath.Split(
222 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); 258 new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
223 259
224 int maxComponentIndex = components.Length - 1; 260 int maxComponentIndex = components.Length - 1;
225 261
226 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the 262 // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
227 // folder itself. This may get more sophisicated later on 263 // folder itself. This may get more sophisicated later on
228 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) 264 if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
@@ -230,13 +266,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
230 saveFolderContentsOnly = true; 266 saveFolderContentsOnly = true;
231 maxComponentIndex--; 267 maxComponentIndex--;
232 } 268 }
233 269
234 m_invPath = String.Empty; 270 m_invPath = String.Empty;
235 for (int i = 0; i <= maxComponentIndex; i++) 271 for (int i = 0; i <= maxComponentIndex; i++)
236 { 272 {
237 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; 273 m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
238 } 274 }
239 275
240 // Annoyingly Split actually returns the original string if the input string consists only of delimiters 276 // Annoyingly Split actually returns the original string if the input string consists only of delimiters
241 // Therefore if we still start with a / after the split, then we need the root folder 277 // Therefore if we still start with a / after the split, then we need the root folder
242 if (m_invPath.Length == 0) 278 if (m_invPath.Length == 0)
@@ -246,25 +282,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
246 else 282 else
247 { 283 {
248 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); 284 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
249 List<InventoryFolderBase> candidateFolders 285 List<InventoryFolderBase> candidateFolders
250 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); 286 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
251 if (candidateFolders.Count > 0) 287 if (candidateFolders.Count > 0)
252 inventoryFolder = candidateFolders[0]; 288 inventoryFolder = candidateFolders[0];
253 } 289 }
254 290
255 // The path may point to an item instead 291 // The path may point to an item instead
256 if (inventoryFolder == null) 292 if (inventoryFolder == null)
257 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); 293 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
258 294
259 if (null == inventoryFolder && null == inventoryItem) 295 if (null == inventoryFolder && null == inventoryItem)
260 { 296 {
261 // We couldn't find the path indicated 297 // We couldn't find the path indicated
262 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); 298 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
263 Exception e = new InventoryArchiverException(errorMessage); 299 Exception e = new InventoryArchiverException(errorMessage);
264 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); 300 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e);
265 throw e; 301 throw e;
266 } 302 }
267 303
268 m_archiveWriter = new TarArchiveWriter(m_saveStream); 304 m_archiveWriter = new TarArchiveWriter(m_saveStream);
269 305
270 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive."); 306 m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive.");
@@ -278,10 +314,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
278 { 314 {
279 m_log.DebugFormat( 315 m_log.DebugFormat(
280 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", 316 "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
281 inventoryFolder.Name, 317 inventoryFolder.Name,
282 inventoryFolder.ID, 318 inventoryFolder.ID,
283 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); 319 m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);
284 320
285 //recurse through all dirs getting dirs and files 321 //recurse through all dirs getting dirs and files
286 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); 322 SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
287 } 323 }
@@ -290,10 +326,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
290 m_log.DebugFormat( 326 m_log.DebugFormat(
291 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", 327 "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
292 inventoryItem.Name, inventoryItem.ID, m_invPath); 328 inventoryItem.Name, inventoryItem.ID, m_invPath);
293 329
294 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); 330 SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
295 } 331 }
296 332
297 // Don't put all this profile information into the archive right now. 333 // Don't put all this profile information into the archive right now.
298 //SaveUsers(); 334 //SaveUsers();
299 335
@@ -352,7 +388,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
352 /// 388 ///
353 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the 389 /// These names are prepended with an inventory folder's UUID so that more than one folder can have the
354 /// same name 390 /// same name
355 /// 391 ///
356 /// <param name="folder"></param> 392 /// <param name="folder"></param>
357 /// <returns></returns> 393 /// <returns></returns>
358 public static string CreateArchiveFolderName(InventoryFolderBase folder) 394 public static string CreateArchiveFolderName(InventoryFolderBase folder)
@@ -366,7 +402,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
366 /// 402 ///
367 /// These names are prepended with an inventory item's UUID so that more than one item can have the 403 /// These names are prepended with an inventory item's UUID so that more than one item can have the
368 /// same name 404 /// same name
369 /// 405 ///
370 /// <param name="item"></param> 406 /// <param name="item"></param>
371 /// <returns></returns> 407 /// <returns></returns>
372 public static string CreateArchiveItemName(InventoryItemBase item) 408 public static string CreateArchiveItemName(InventoryItemBase item)
@@ -412,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
412 public string CreateControlFile(Dictionary<string, object> options) 448 public string CreateControlFile(Dictionary<string, object> options)
413 { 449 {
414 int majorVersion, minorVersion; 450 int majorVersion, minorVersion;
415 451
416 if (options.ContainsKey("home")) 452 if (options.ContainsKey("home"))
417 { 453 {
418 majorVersion = 1; 454 majorVersion = 1;
@@ -422,10 +458,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
422 { 458 {
423 majorVersion = 0; 459 majorVersion = 0;
424 minorVersion = 3; 460 minorVersion = 3;
425 } 461 }
426 462
427 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); 463 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion);
428 464
429 StringWriter sw = new StringWriter(); 465 StringWriter sw = new StringWriter();
430 XmlTextWriter xtw = new XmlTextWriter(sw); 466 XmlTextWriter xtw = new XmlTextWriter(sw);
431 xtw.Formatting = Formatting.Indented; 467 xtw.Formatting = Formatting.Indented;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index ac22c3f..cf87010 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -47,18 +47,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule 47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 public string Name { get { return "Inventory Archiver Module"; } } 51 public string Name { get { return "Inventory Archiver Module"; } }
52 52
53 public bool IsSharedModule { get { return true; } } 53 public bool IsSharedModule { get { return true; } }
54 54
55 /// <value> 55 /// <value>
56 /// Enable or disable checking whether the iar user is actually logged in 56 /// Enable or disable checking whether the iar user is actually logged in
57 /// </value> 57 /// </value>
58// public bool DisablePresenceChecks { get; set; } 58// public bool DisablePresenceChecks { get; set; }
59 59
60 public event InventoryArchiveSaved OnInventoryArchiveSaved; 60 public event InventoryArchiveSaved OnInventoryArchiveSaved;
61 61
62 /// <summary> 62 /// <summary>
63 /// The file to load and save inventory if no filename has been specified 63 /// The file to load and save inventory if no filename has been specified
64 /// </summary> 64 /// </summary>
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
68 /// Pending save completions initiated from the console 68 /// Pending save completions initiated from the console
69 /// </value> 69 /// </value>
70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>(); 70 protected List<Guid> m_pendingConsoleSaves = new List<Guid>();
71 71
72 /// <value> 72 /// <value>
73 /// All scenes that this module knows about 73 /// All scenes that this module knows about
74 /// </value> 74 /// </value>
@@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
106 { 106 {
107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this); 107 scene.RegisterModuleInterface<IInventoryArchiverModule>(this);
108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; 108 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted;
109 109
110 scene.AddCommand( 110 scene.AddCommand(
111 "Archiving", this, "load iar", 111 "Archiving", this, "load iar",
112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]", 112 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]",
@@ -119,11 +119,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
119 + "<IAR path> is the filesystem path or URI from which to load the IAR." 119 + "<IAR path> is the filesystem path or URI from which to load the IAR."
120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), 120 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME),
121 HandleLoadInvConsoleCommand); 121 HandleLoadInvConsoleCommand);
122 122
123 scene.AddCommand( 123 scene.AddCommand(
124 "Archiving", this, "save iar", 124 "Archiving", this, "save iar",
125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-v|--verbose]", 125 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
126 "Save user inventory archive (IAR).", 126 "Save user inventory archive (IAR).",
127 "<first> is the user's first name.\n" 127 "<first> is the user's first name.\n"
128 + "<last> is the user's last name.\n" 128 + "<last> is the user's last name.\n"
129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n" 129 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n"
@@ -131,32 +131,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME) 131 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME)
132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 132 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
133 + "-c|--creators preserves information about foreign creators.\n" 133 + "-c|--creators preserves information about foreign creators.\n"
134 + "-e|--exclude=<name/uuid> don't save the inventory item in archive" + Environment.NewLine
135 + "-f|--excludefolder=<folder/uuid> don't save contents of the folder in archive" + Environment.NewLine
134 + "-v|--verbose extra debug messages.\n" 136 + "-v|--verbose extra debug messages.\n"
135 + "--noassets stops assets being saved to the IAR.", 137 + "--noassets stops assets being saved to the IAR.",
136 HandleSaveInvConsoleCommand); 138 HandleSaveInvConsoleCommand);
137 139
138 m_aScene = scene; 140 m_aScene = scene;
139 } 141 }
140 142
141 m_scenes[scene.RegionInfo.RegionID] = scene; 143 m_scenes[scene.RegionInfo.RegionID] = scene;
142 } 144 }
143 145
144 public void PostInitialise() {} 146 public void PostInitialise() {}
145 147
146 public void Close() {} 148 public void Close() {}
147 149
148 /// <summary> 150 /// <summary>
149 /// Trigger the inventory archive saved event. 151 /// Trigger the inventory archive saved event.
150 /// </summary> 152 /// </summary>
151 protected internal void TriggerInventoryArchiveSaved( 153 protected internal void TriggerInventoryArchiveSaved(
152 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 154 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
153 Exception reportedException) 155 Exception reportedException)
154 { 156 {
155 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved; 157 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved;
156 if (handlerInventoryArchiveSaved != null) 158 if (handlerInventoryArchiveSaved != null)
157 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); 159 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
158 } 160 }
159 161
160 public bool ArchiveInventory( 162 public bool ArchiveInventory(
161 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) 163 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
162 { 164 {
@@ -164,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
164 } 166 }
165 167
166 public bool ArchiveInventory( 168 public bool ArchiveInventory(
167 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, 169 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
168 Dictionary<string, object> options) 170 Dictionary<string, object> options)
169 { 171 {
170 if (m_scenes.Count > 0) 172 if (m_scenes.Count > 0)
@@ -188,7 +190,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
188 190
189 return false; 191 return false;
190 } 192 }
191 193
192 return true; 194 return true;
193// } 195// }
194// else 196// else
@@ -202,15 +204,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
202 204
203 return false; 205 return false;
204 } 206 }
205 207
206 public bool ArchiveInventory( 208 public bool ArchiveInventory(
207 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
208 Dictionary<string, object> options) 210 Dictionary<string, object> options)
209 { 211 {
210 if (m_scenes.Count > 0) 212 if (m_scenes.Count > 0)
211 { 213 {
212 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
213 215
214 if (userInfo != null) 216 if (userInfo != null)
215 { 217 {
216// if (CheckPresence(userInfo.PrincipalID)) 218// if (CheckPresence(userInfo.PrincipalID))
@@ -228,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
228 230
229 return false; 231 return false;
230 } 232 }
231 233
232 return true; 234 return true;
233// } 235// }
234// else 236// else
@@ -239,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
239// } 241// }
240 } 242 }
241 } 243 }
242 244
243 return false; 245 return false;
244 } 246 }
245 247
@@ -247,9 +249,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
247 { 249 {
248 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>()); 250 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
249 } 251 }
250 252
251 public bool DearchiveInventory( 253 public bool DearchiveInventory(
252 string firstName, string lastName, string invPath, string pass, Stream loadStream, 254 string firstName, string lastName, string invPath, string pass, Stream loadStream,
253 Dictionary<string, object> options) 255 Dictionary<string, object> options)
254 { 256 {
255 if (m_scenes.Count > 0) 257 if (m_scenes.Count > 0)
@@ -295,22 +297,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
295 297
296 return false; 298 return false;
297 } 299 }
298 300
299 public bool DearchiveInventory( 301 public bool DearchiveInventory(
300 string firstName, string lastName, string invPath, string pass, string loadPath, 302 string firstName, string lastName, string invPath, string pass, string loadPath,
301 Dictionary<string, object> options) 303 Dictionary<string, object> options)
302 { 304 {
303 if (m_scenes.Count > 0) 305 if (m_scenes.Count > 0)
304 { 306 {
305 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 307 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
306 308
307 if (userInfo != null) 309 if (userInfo != null)
308 { 310 {
309// if (CheckPresence(userInfo.PrincipalID)) 311// if (CheckPresence(userInfo.PrincipalID))
310// { 312// {
311 InventoryArchiveReadRequest request; 313 InventoryArchiveReadRequest request;
312 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 314 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
313 315
314 try 316 try
315 { 317 {
316 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 318 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
@@ -324,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
324 326
325 return false; 327 return false;
326 } 328 }
327 329
328 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 330 UpdateClientWithLoadedNodes(userInfo, request.Execute());
329 331
330 return true; 332 return true;
@@ -340,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
340 342
341 return false; 343 return false;
342 } 344 }
343 345
344 /// <summary> 346 /// <summary>
345 /// Load inventory from an inventory file archive 347 /// Load inventory from an inventory file archive
346 /// </summary> 348 /// </summary>
@@ -351,26 +353,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
351 { 353 {
352 Dictionary<string, object> options = new Dictionary<string, object>(); 354 Dictionary<string, object> options = new Dictionary<string, object>();
353 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); 355 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
354 356
355 List<string> mainParams = optionSet.Parse(cmdparams); 357 List<string> mainParams = optionSet.Parse(cmdparams);
356 358
357 if (mainParams.Count < 6) 359 if (mainParams.Count < 6)
358 { 360 {
359 m_log.Error( 361 m_log.Error(
360 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]"); 362 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
361 return; 363 return;
362 } 364 }
363 365
364 string firstName = mainParams[2]; 366 string firstName = mainParams[2];
365 string lastName = mainParams[3]; 367 string lastName = mainParams[3];
366 string invPath = mainParams[4]; 368 string invPath = mainParams[4];
367 string pass = mainParams[5]; 369 string pass = mainParams[5];
368 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 370 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
369 371
370 m_log.InfoFormat( 372 m_log.InfoFormat(
371 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", 373 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
372 loadPath, invPath, firstName, lastName); 374 loadPath, invPath, firstName, lastName);
373 375
374 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) 376 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options))
375 m_log.InfoFormat( 377 m_log.InfoFormat(
376 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", 378 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}",
@@ -381,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
381 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 383 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
382 } 384 }
383 } 385 }
384 386
385 /// <summary> 387 /// <summary>
386 /// Save inventory to a file archive 388 /// Save inventory to a file archive
387 /// </summary> 389 /// </summary>
@@ -398,6 +400,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
398 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); 400 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; });
399 ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); 401 ops.Add("c|creators", delegate(string v) { options["creators"] = v; });
400 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 402 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
403 ops.Add("e|exclude=", delegate(string v)
404 {
405 if (!options.ContainsKey("exclude"))
406 options["exclude"] = new List<String>();
407 ((List<String>)options["exclude"]).Add(v);
408 });
409 ops.Add("f|excludefolder=", delegate(string v)
410 {
411 if (!options.ContainsKey("excludefolders"))
412 options["excludefolders"] = new List<String>();
413 ((List<String>)options["excludefolders"]).Add(v);
414 });
401 415
402 List<string> mainParams = ops.Parse(cmdparams); 416 List<string> mainParams = ops.Parse(cmdparams);
403 417
@@ -406,10 +420,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 if (mainParams.Count < 6) 420 if (mainParams.Count < 6)
407 { 421 {
408 m_log.Error( 422 m_log.Error(
409 "[INVENTORY ARCHIVER]: usage is save iar [-h|--home=<url>] [--noassets] <first name> <last name> <inventory path> <user password> [<save file path>] [-c|--creators] [-v|--verbose]"); 423 "[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
410 return; 424 return;
411 } 425 }
412 426
413 if (options.ContainsKey("home")) 427 if (options.ContainsKey("home"))
414 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR"); 428 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR");
415 429
@@ -418,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 string invPath = mainParams[4]; 432 string invPath = mainParams[4];
419 string pass = mainParams[5]; 433 string pass = mainParams[5];
420 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); 434 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
421 435
422 m_log.InfoFormat( 436 m_log.InfoFormat(
423 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", 437 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}",
424 savePath, invPath, firstName, lastName); 438 savePath, invPath, firstName, lastName);
@@ -433,9 +447,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
433 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); 447 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
434 } 448 }
435 } 449 }
436 450
437 private void SaveInvConsoleCommandCompleted( 451 private void SaveInvConsoleCommandCompleted(
438 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 452 Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
439 Exception reportedException) 453 Exception reportedException)
440 { 454 {
441 lock (m_pendingConsoleSaves) 455 lock (m_pendingConsoleSaves)
@@ -445,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
445 else 459 else
446 return; 460 return;
447 } 461 }
448 462
449 if (succeeded) 463 if (succeeded)
450 { 464 {
451 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName); 465 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive for {0} {1}", userInfo.FirstName, userInfo.LastName);
@@ -453,11 +467,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
453 else 467 else
454 { 468 {
455 m_log.ErrorFormat( 469 m_log.ErrorFormat(
456 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}", 470 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}",
457 userInfo.FirstName, userInfo.LastName, reportedException.Message); 471 userInfo.FirstName, userInfo.LastName, reportedException.Message);
458 } 472 }
459 } 473 }
460 474
461 /// <summary> 475 /// <summary>
462 /// Get user information for the given name. 476 /// Get user information for the given name.
463 /// </summary> 477 /// </summary>
@@ -467,13 +481,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
467 /// <returns></returns> 481 /// <returns></returns>
468 protected UserAccount GetUserInfo(string firstName, string lastName, string pass) 482 protected UserAccount GetUserInfo(string firstName, string lastName, string pass)
469 { 483 {
470 UserAccount account 484 UserAccount account
471 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); 485 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName);
472 486
473 if (null == account) 487 if (null == account)
474 { 488 {
475 m_log.ErrorFormat( 489 m_log.ErrorFormat(
476 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}", 490 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}",
477 firstName, lastName); 491 firstName, lastName);
478 return null; 492 return null;
479 } 493 }
@@ -488,7 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
488 else 502 else
489 { 503 {
490 m_log.ErrorFormat( 504 m_log.ErrorFormat(
491 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.", 505 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.",
492 firstName, lastName); 506 firstName, lastName);
493 return null; 507 return null;
494 } 508 }
@@ -499,7 +513,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
499 return null; 513 return null;
500 } 514 }
501 } 515 }
502 516
503 /// <summary> 517 /// <summary>
504 /// Notify the client of loaded nodes if they are logged in 518 /// Notify the client of loaded nodes if they are logged in
505 /// </summary> 519 /// </summary>
@@ -508,22 +522,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
508 { 522 {
509 if (loadedNodes.Count == 0) 523 if (loadedNodes.Count == 0)
510 return; 524 return;
511 525
512 foreach (Scene scene in m_scenes.Values) 526 foreach (Scene scene in m_scenes.Values)
513 { 527 {
514 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID); 528 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID);
515 529
516 if (user != null && !user.IsChildAgent) 530 if (user != null && !user.IsChildAgent)
517 { 531 {
518 foreach (InventoryNodeBase node in loadedNodes) 532 foreach (InventoryNodeBase node in loadedNodes)
519 { 533 {
520// m_log.DebugFormat( 534// m_log.DebugFormat(
521// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", 535// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
522// user.Name, node.Name); 536// user.Name, node.Name);
523 537
524 user.ControllingClient.SendBulkUpdateInventory(node); 538 user.ControllingClient.SendBulkUpdateInventory(node);
525 } 539 }
526 540
527 break; 541 break;
528 } 542 }
529 } 543 }
@@ -538,7 +552,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538// { 552// {
539// if (DisablePresenceChecks) 553// if (DisablePresenceChecks)
540// return true; 554// return true;
541// 555//
542// foreach (Scene scene in m_scenes.Values) 556// foreach (Scene scene in m_scenes.Values)
543// { 557// {
544// ScenePresence p; 558// ScenePresence p;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 19ef571..1056865 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.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 InventoryArchiveTestCase 51 public class InventoryArchiveTestCase : OpenSimTestCase
52 { 52 {
53 protected ManualResetEvent mre = new ManualResetEvent(false); 53 protected ManualResetEvent mre = new ManualResetEvent(false);
54 54
@@ -84,8 +84,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
84 protected string m_coaItemName = "Coalesced Item"; 84 protected string m_coaItemName = "Coalesced Item";
85 85
86 [SetUp] 86 [SetUp]
87 public virtual void SetUp() 87 public override void SetUp()
88 { 88 {
89 base.SetUp();
89 m_iarStream = new MemoryStream(m_iarStreamBytes); 90 m_iarStream = new MemoryStream(m_iarStreamBytes);
90 } 91 }
91 92
@@ -100,7 +101,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
100// log4net.Config.XmlConfigurator.Configure(); 101// log4net.Config.XmlConfigurator.Configure();
101 102
102 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 103 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
103 Scene scene = SceneHelpers.SetupScene(); 104 Scene scene = new SceneHelpers().SetupScene();
104 SceneHelpers.SetupSceneModules(scene, archiverModule); 105 SceneHelpers.SetupSceneModules(scene, archiverModule);
105 106
106 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 107 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index e409c8e..b112b6d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
61 SerialiserModule serialiserModule = new SerialiserModule(); 61 SerialiserModule serialiserModule = new SerialiserModule();
62 m_archiverModule = new InventoryArchiverModule(); 62 m_archiverModule = new InventoryArchiverModule();
63 63
64 m_scene = 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 67
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
index 417c20c..6eb3605 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
@@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
62 62
63 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 63 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
64 64
65 Scene scene = SceneHelpers.SetupScene(); 65 Scene scene = new SceneHelpers().SetupScene();
66 SceneHelpers.SetupSceneModules(scene, archiverModule); 66 SceneHelpers.SetupSceneModules(scene, archiverModule);
67 67
68 // Create user 68 // Create user
@@ -179,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
179 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 179 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
180 180
181 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene 181 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene
182 Scene scene = SceneHelpers.SetupScene(); 182 Scene scene = new SceneHelpers().SetupScene();
183 183
184 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 184 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
185 185
@@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
222 222
223 SerialiserModule serialiserModule = new SerialiserModule(); 223 SerialiserModule serialiserModule = new SerialiserModule();
224 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 224 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
225 Scene scene = SceneHelpers.SetupScene(); 225 Scene scene = new SceneHelpers().SetupScene();
226 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 226 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
227 227
228 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); 228 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password");
@@ -247,7 +247,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
247 247
248 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 248 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
249 249
250 Scene scene = SceneHelpers.SetupScene(); 250 Scene scene = new SceneHelpers().SetupScene();
251 SceneHelpers.SetupSceneModules(scene, archiverModule); 251 SceneHelpers.SetupSceneModules(scene, archiverModule);
252 252
253 // Create user 253 // Create user
@@ -326,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
326 TestHelpers.InMethod(); 326 TestHelpers.InMethod();
327// log4net.Config.XmlConfigurator.Configure(); 327// log4net.Config.XmlConfigurator.Configure();
328 328
329 Scene scene = SceneHelpers.SetupScene(); 329 Scene scene = new SceneHelpers().SetupScene();
330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
331 331
332 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 332 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
@@ -393,7 +393,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
393 TestHelpers.InMethod(); 393 TestHelpers.InMethod();
394 //log4net.Config.XmlConfigurator.Configure(); 394 //log4net.Config.XmlConfigurator.Configure();
395 395
396 Scene scene = SceneHelpers.SetupScene(); 396 Scene scene = new SceneHelpers().SetupScene();
397 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 397 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
398 398
399 string folder1ExistingName = "a"; 399 string folder1ExistingName = "a";
@@ -444,7 +444,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
444 TestHelpers.InMethod(); 444 TestHelpers.InMethod();
445// log4net.Config.XmlConfigurator.Configure(); 445// log4net.Config.XmlConfigurator.Configure();
446 446
447 Scene scene = SceneHelpers.SetupScene(); 447 Scene scene = new SceneHelpers().SetupScene();
448 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 448 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
449 449
450 string folder1ExistingName = "a"; 450 string folder1ExistingName = "a";
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index bc5c1ff..92cf9d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -240,13 +240,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
240 { 240 {
241 ScenePresence sp = scene.GetScenePresence(client.AgentId); 241 ScenePresence sp = scene.GetScenePresence(client.AgentId);
242 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>(); 242 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
243 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>(); 243
244 if (transferMod != null && sp != null && eq != null) 244 if (transferMod != null && sp != null)
245 transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); 245 transferMod.DoTeleport(
246 sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f),
247 Vector3.UnitX, teleportflags);
246 } 248 }
247 } 249 }
248 } 250 }
249 } 251 }
250 } 252 }
251 } 253 }
252} 254} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index dcfdf8f..a889984 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -151,6 +151,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
151 Scene scene = (Scene)(client.Scene); 151 Scene scene = (Scene)(client.Scene);
152 ScenePresence presence = scene.GetScenePresence(client.AgentId); 152 ScenePresence presence = scene.GetScenePresence(client.AgentId);
153 153
154 // Round up Z co-ordinate rather than round-down by casting. This stops tall avatars from being given
155 // a teleport Z co-ordinate by short avatars that drops them through or embeds them in thin floors on
156 // arrival.
157 //
158 // Ideally we would give the exact float position adjusting for the relative height of the two avatars
159 // but it looks like a float component isn't possible with a parcel ID.
154 UUID dest = Util.BuildFakeParcelID( 160 UUID dest = Util.BuildFakeParcelID(
155 scene.RegionInfo.RegionHandle, 161 scene.RegionInfo.RegionHandle,
156 (uint)presence.AbsolutePosition.X, 162 (uint)presence.AbsolutePosition.X,
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index 8101ca2..87ca327 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,14 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 // This can be reduced later as the loader will determine
61 // whether we are needed
62 if (config.Configs["Profile"] != null)
63 {
64 if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
65 return;
66 }
67
68 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
69 m_Enabled = true; 61 m_Enabled = true;
70 } 62 }