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.cs194
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs399
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs78
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs235
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs87
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs247
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs109
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs181
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs178
18 files changed, 1409 insertions, 435 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2f67c4e..92beed2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 43using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces;
44 45
45namespace OpenSim.Region.CoreModules.Avatar.Attachments 46namespace OpenSim.Region.CoreModules.Avatar.Attachments
46{ 47{
@@ -303,6 +304,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
303 if (DebugLevel > 0) 304 if (DebugLevel > 0)
304 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 305 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
305 306
307 XmlDocument doc = new XmlDocument();
308 string stateData = String.Empty;
309
310 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
311 if (attServ != null)
312 {
313 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
314 stateData = attServ.Get(sp.UUID.ToString());
315 if (stateData != String.Empty)
316 {
317 try
318 {
319 doc.LoadXml(stateData);
320 }
321 catch { }
322 }
323 }
324
325 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
326
327 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
328 if (nodes.Count > 0)
329 {
330 foreach (XmlNode n in nodes)
331 {
332 XmlElement elem = (XmlElement)n;
333 string itemID = elem.GetAttribute("ItemID");
334 string xml = elem.InnerXml;
335
336 itemData[new UUID(itemID)] = xml;
337 }
338 }
339
340
306 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 341 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
307 342
308 // Let's get all items at once, so they get cached 343 // Let's get all items at once, so they get cached
@@ -330,10 +365,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
330 365
331 try 366 try
332 { 367 {
368 string xmlData;
369 XmlDocument d = null;
370 UUID asset;
371 if (itemData.TryGetValue(attach.ItemID, out xmlData))
372 {
373 d = new XmlDocument();
374 d.LoadXml(xmlData);
375 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
376 }
377
333 // If we're an NPC then skip all the item checks and manipulations since we don't have an 378 // If we're an NPC then skip all the item checks and manipulations since we don't have an
334 // inventory right now. 379 // inventory right now.
335 RezSingleAttachmentFromInventoryInternal( 380 RezSingleAttachmentFromInventoryInternal(
336 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 381 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
337 } 382 }
338 catch (Exception e) 383 catch (Exception e)
339 { 384 {
@@ -361,27 +406,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 406
362 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 407 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
363 408
364 foreach (SceneObjectGroup so in attachments)
365 {
366 // Scripts MUST be snapshotted before the object is
367 // removed from the scene because doing otherwise will
368 // clobber the run flag
369 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
370 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
371 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
372 409
373// m_log.DebugFormat( 410 if (sp.PresenceType != PresenceType.Npc)
374// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}",
375// so.Name, sp.Name, m_scene.Name, scriptStates[so]);
376 }
377
378 lock (sp.AttachmentsSyncLock)
379 { 411 {
380 foreach (SceneObjectGroup so in attachments) 412 foreach (SceneObjectGroup so in attachments)
381 UpdateDetachedObject(sp, so, scriptStates[so]); 413 {
382 414 // Scripts MUST be snapshotted before the object is
383 sp.ClearAttachments(); 415 // removed from the scene because doing otherwise will
416 // clobber the run flag
417 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
418 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
419 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
420 }
421
422 lock (sp.AttachmentsSyncLock)
423 {
424 foreach (SceneObjectGroup so in attachments)
425 UpdateDetachedObject(sp, so, scriptStates[so]);
426 sp.ClearAttachments();
427 }
384 } 428 }
429 else
430 {
431 lock (sp.AttachmentsSyncLock)
432 {
433 foreach (SceneObjectGroup so in attachments)
434 UpdateDetachedObject(sp, so, String.Empty);
435 sp.ClearAttachments();
436 }
437 }
385 } 438 }
386 439
387 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 440 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
@@ -402,20 +455,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
402 sp.ClearAttachments(); 455 sp.ClearAttachments();
403 } 456 }
404 457
405 public bool AttachObject( 458 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
406 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append)
407 { 459 {
408 if (!Enabled) 460 if (!Enabled)
409 return false; 461 return false;
410 462
411 group.DetachFromBackup(); 463 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
412
413 bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
414
415 if (!success)
416 group.AttachToBackup();
417
418 return success;
419 } 464 }
420 465
421 /// <summary> 466 /// <summary>
@@ -428,10 +473,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
428 /// <param name='silent'></param> 473 /// <param name='silent'></param>
429 /// <param name='addToInventory'>If true then add object to user inventory.</param> 474 /// <param name='addToInventory'>If true then add object to user inventory.</param>
430 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 475 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
431 /// <param name='append'>Append to attachment point rather than replace.</param> 476 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
432 private bool AttachObjectInternal(
433 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
434 { 477 {
478// m_log.DebugFormat(
479// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
480// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
481
482 if (sp.GetAttachments().Contains(group))
483 {
484// m_log.WarnFormat(
485// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
486// group.Name, group.LocalId, sp.Name, AttachmentPt);
487
488 return false;
489 }
490
435 if (group.GetSittingAvatarsCount() != 0) 491 if (group.GetSittingAvatarsCount() != 0)
436 { 492 {
437 if (DebugLevel > 0) 493 if (DebugLevel > 0)
@@ -443,6 +499,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
443 } 499 }
444 500
445 Vector3 attachPos = group.AbsolutePosition; 501 Vector3 attachPos = group.AbsolutePosition;
502
503 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
504 // be removed when that functionality is implemented in opensim
505 attachmentPt &= 0x7f;
506
446 // If the attachment point isn't the same as the one previously used 507 // If the attachment point isn't the same as the one previously used
447 // set it's offset position = 0 so that it appears on the attachment point 508 // set it's offset position = 0 so that it appears on the attachment point
448 // and not in a weird location somewhere unknown. 509 // and not in a weird location somewhere unknown.
@@ -481,9 +542,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
481 attachPos = Vector3.Zero; 542 attachPos = Vector3.Zero;
482 } 543 }
483 544
484 group.AttachmentPoint = attachmentPt;
485 group.AbsolutePosition = attachPos;
486
487 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 545 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
488 546
489 if (attachments.Contains(group)) 547 if (attachments.Contains(group))
@@ -516,6 +574,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
516 574
517 lock (sp.AttachmentsSyncLock) 575 lock (sp.AttachmentsSyncLock)
518 { 576 {
577 group.AttachmentPoint = attachmentPt;
578 group.AbsolutePosition = attachPos;
579
519 if (addToInventory && sp.PresenceType != PresenceType.Npc) 580 if (addToInventory && sp.PresenceType != PresenceType.Npc)
520 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 581 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
521 582
@@ -546,7 +607,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
546 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 607 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
547 } 608 }
548 609
549 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 610 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
611 {
612 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
613 }
614
615 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
550 { 616 {
551 if (!Enabled) 617 if (!Enabled)
552 return null; 618 return null;
@@ -584,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
584 bool append = (AttachmentPt & 0x80) != 0; 650 bool append = (AttachmentPt & 0x80) != 0;
585 AttachmentPt &= 0x7f; 651 AttachmentPt &= 0x7f;
586 652
587 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 653 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
588 } 654 }
589 655
590 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 656 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -649,26 +715,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
649 if (changed && m_scene.AvatarFactory != null) 715 if (changed && m_scene.AvatarFactory != null)
650 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 716 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
651 717
718 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
719
652 sp.RemoveAttachment(so); 720 sp.RemoveAttachment(so);
653 so.FromItemID = UUID.Zero; 721 so.FromItemID = UUID.Zero;
654 722
723 so.AttachedAvatar = UUID.Zero;
724 so.ClearPartAttachmentData();
725
655 SceneObjectPart rootPart = so.RootPart; 726 SceneObjectPart rootPart = so.RootPart;
727
728 rootPart.SetParentLocalId(0);
656 so.AbsolutePosition = absolutePos; 729 so.AbsolutePosition = absolutePos;
657 if (absoluteRot != Quaternion.Identity) 730 if (absoluteRot != Quaternion.Identity)
658 { 731 {
659 so.UpdateGroupRotationR(absoluteRot); 732 so.UpdateGroupRotationR(absoluteRot);
660 } 733 }
661 so.AttachedAvatar = UUID.Zero; 734
662 rootPart.SetParentLocalId(0); 735 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
663 so.ClearPartAttachmentData(); 736
664 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); 737 // not physical, not temporary, phaton, not volume detector
738// so.UpdatePrimFlags(rootPart.LocalId,false,false,true,rootPart.VolumeDetectActive);
739
740 // restore full physical state instead
741 so.ApplyPhysics();
742
665 so.HasGroupChanged = true; 743 so.HasGroupChanged = true;
666 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
667 rootPart.Rezzed = DateTime.Now; 744 rootPart.Rezzed = DateTime.Now;
668 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
669 so.AttachToBackup(); 745 so.AttachToBackup();
670 m_scene.EventManager.TriggerParcelPrimCountTainted(); 746 m_scene.EventManager.TriggerParcelPrimCountTainted();
671 rootPart.ScheduleFullUpdate(); 747
672 rootPart.ClearUndoState(); 748 rootPart.ClearUndoState();
673 749
674 List<UUID> uuids = new List<UUID>(); 750 List<UUID> uuids = new List<UUID>();
@@ -678,6 +754,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
678 } 754 }
679 755
680 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 756 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
757
758 // Attach (NULL) stops scripts. We don't want that. Resume them.
759 so.ResumeScripts();
760 so.ScheduleGroupForTerseUpdate();
761 so.RootPart.ScheduleFullUpdate();
681 } 762 }
682 763
683 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 764 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -848,8 +929,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
848 929
849 so.AttachedAvatar = sp.UUID; 930 so.AttachedAvatar = sp.UUID;
850 931
851 if (so.RootPart.PhysActor != null) 932 foreach (SceneObjectPart part in so.Parts)
852 so.RootPart.RemoveFromPhysics(); 933 {
934// if (part.KeyframeMotion != null)
935// part.KeyframeMotion.Suspend();
936
937 if (part.PhysActor != null)
938 {
939 part.RemoveFromPhysics();
940 }
941 }
853 942
854 so.AbsolutePosition = attachOffset; 943 so.AbsolutePosition = attachOffset;
855 so.RootPart.AttachedPos = attachOffset; 944 so.RootPart.AttachedPos = attachOffset;
@@ -971,6 +1060,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 // Remove the object from the scene so no more updates 1060 // Remove the object from the scene so no more updates
972 // are sent. Doing this before the below changes will ensure 1061 // are sent. Doing this before the below changes will ensure
973 // updates can't cause "HUD artefacts" 1062 // updates can't cause "HUD artefacts"
1063
974 m_scene.DeleteSceneObject(so, false, false); 1064 m_scene.DeleteSceneObject(so, false, false);
975 1065
976 // Prepare sog for storage 1066 // Prepare sog for storage
@@ -992,7 +1082,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
992 } 1082 }
993 1083
994 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1084 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
995 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1085 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
996 { 1086 {
997 if (m_invAccessModule == null) 1087 if (m_invAccessModule == null)
998 return null; 1088 return null;
@@ -1043,7 +1133,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 // This will throw if the attachment fails 1133 // This will throw if the attachment fails
1044 try 1134 try
1045 { 1135 {
1046 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1136 if (doc != null)
1137 {
1138 objatt.LoadScriptState(doc);
1139 objatt.ResetOwnerChangeFlag();
1140 }
1141
1142 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
1047 } 1143 }
1048 catch (Exception e) 1144 catch (Exception e)
1049 { 1145 {
@@ -1197,7 +1293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1197 AttachmentPt &= 0x7f; 1293 AttachmentPt &= 0x7f;
1198 1294
1199 // Calls attach with a Zero position 1295 // Calls attach with a Zero position
1200 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1296 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, true, append))
1201 { 1297 {
1202 if (DebugLevel > 0) 1298 if (DebugLevel > 0)
1203 m_log.Debug( 1299 m_log.Debug(
@@ -1205,7 +1301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1205 + ", AttachmentPoint: " + AttachmentPt); 1301 + ", AttachmentPoint: " + AttachmentPt);
1206 1302
1207 // Save avatar attachment information 1303 // Save avatar attachment information
1208 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1304 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1209 } 1305 }
1210 } 1306 }
1211 catch (Exception e) 1307 catch (Exception e)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ac3add..34b38b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
200 Assert.That(so.Backup, Is.True); 200 Assert.That(so.Backup, Is.True);
201 201
202 m_numberOfAttachEventsFired = 0; 202 m_numberOfAttachEventsFired = 0;
203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
204 204
205 // Check status on scene presence 205 // Check status on scene presence
206 Assert.That(sp.HasAttachments(), Is.True); 206 Assert.That(sp.HasAttachments(), Is.True);
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); 248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
249 249
250 m_numberOfAttachEventsFired = 0; 250 m_numberOfAttachEventsFired = 0;
251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false); 251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
252 252
253 // Check status on scene presence 253 // Check status on scene presence
254 Assert.That(sp.HasAttachments(), Is.True); 254 Assert.That(sp.HasAttachments(), Is.True);
@@ -281,7 +281,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
281 281
282 // Test wearing a different attachment from the ground. 282 // Test wearing a different attachment from the ground.
283 { 283 {
284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
285 285
286 // Check status on scene presence 286 // Check status on scene presence
287 Assert.That(sp.HasAttachments(), Is.True); 287 Assert.That(sp.HasAttachments(), Is.True);
@@ -314,7 +314,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
314 314
315 // Test rewearing an already worn attachment from ground. Nothing should happen. 315 // Test rewearing an already worn attachment from ground. Nothing should happen.
316 { 316 {
317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
318 318
319 // Check status on scene presence 319 // Check status on scene presence
320 Assert.That(sp.HasAttachments(), Is.True); 320 Assert.That(sp.HasAttachments(), Is.True);
@@ -372,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
372 sp2.AbsolutePosition = new Vector3(0, 0, 0); 372 sp2.AbsolutePosition = new Vector3(0, 0, 0);
373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
374 374
375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
376 376
377 Assert.That(sp.HasAttachments(), Is.False); 377 Assert.That(sp.HasAttachments(), Is.False);
378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -670,7 +670,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
670 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 670 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
671 671
672 SceneObjectGroup rezzedSo 672 SceneObjectGroup rezzedSo
673 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 673 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
674 674
675 // Wait for chat to signal rezzed script has been started. 675 // Wait for chat to signal rezzed script has been started.
676 m_chatEvent.WaitOne(60000); 676 m_chatEvent.WaitOne(60000);
@@ -689,7 +689,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
690 690
691 // Re-rez the attachment to check script running state 691 // Re-rez the attachment to check script running state
692 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 692 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
693 693
694 // Wait for chat to signal rezzed script has been started. 694 // Wait for chat to signal rezzed script has been started.
695 m_chatEvent.WaitOne(60000); 695 m_chatEvent.WaitOne(60000);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..cdcd6b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -188,27 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
188 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
189 if (visualParams != null) 189 if (visualParams != null)
190 { 190 {
191 // string[] visualParamsStrings = new string[visualParams.Length];
192 // for (int i = 0; i < visualParams.Length; i++)
193 // visualParamsStrings[i] = visualParams[i].ToString();
194 // m_log.DebugFormat(
195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
196 // client.Name, string.Join(", ", visualParamsStrings));
197/*
198 float oldHeight = sp.Appearance.AvatarHeight;
199 changed = sp.Appearance.SetVisualParams(visualParams);
200
201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams); 191 changed = sp.Appearance.SetVisualParams(visualParams);
207// float off = sp.Appearance.AvatarFeetOffset;
208// Vector3 box = sp.Appearance.AvatarBoxSize;
209// if(oldoff != off || oldbox != box)
210// ((ScenePresence)sp).SetSize(box,off);
211
212 } 192 }
213 193
214 // Process the baked texture array 194 // Process the baked texture array
@@ -222,9 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
222 202
223// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
224 204
225 // If bake textures are missing and this is not an NPC, request a rebake from client 205 UpdateBakedTextureCache(sp, cacheItems);
226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
227 RequestRebake(sp, true);
228 206
229 // This appears to be set only in the final stage of the appearance 207 // This appears to be set only in the final stage of the appearance
230 // update transaction. In theory, we should be able to do an immediate 208 // update transaction. In theory, we should be able to do an immediate
@@ -251,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
251 private void SendAppearance(ScenePresence sp) 229 private void SendAppearance(ScenePresence sp)
252 { 230 {
253 // Send the appearance to everyone in the scene 231 // Send the appearance to everyone in the scene
254 sp.SendAppearanceToAllOtherClients(); 232 sp.SendAppearanceToAllOtherAgents();
255 233
256 // Send animations back to the avatar as well 234 // Send animations back to the avatar as well
257 sp.Animator.SendAnimPack(); 235 sp.Animator.SendAnimPack();
@@ -377,114 +355,322 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 355 }
378 } 356 }
379 357
380 public bool ValidateBakedTextureCache(IScenePresence sp) 358 // called on textures update
359 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 360 {
382 bool defonly = true; // are we only using default textures 361 // npcs dont have baked cache
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 362 if (((ScenePresence)sp).isNPC)
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 363 return true;
385 WearableCacheItem[] wearableCache = null; 364
386 365 // uploaded baked textures will be in assets local cache
387 // Cache wearable data for teleport. 366 IAssetService cache = m_scene.AssetService;
388 // Only makes sense if there's a bake module and a cache module 367 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
389 if (bakedModule != null && cache != null) 368
369 int validDirtyBakes = 0;
370 int hits = 0;
371
372 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
373 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
374
375 if (wearableCache == null)
376 {
377 wearableCache = WearableCacheItem.GetDefaultCacheItem();
378 }
379
380 List<UUID> missing = new List<UUID>();
381
382 // Process received baked textures
383 for (int i = 0; i < cacheItems.Length; i++)
390 { 384 {
391 try 385 int idx = (int)cacheItems[i].TextureIndex;
386 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
387
388 // No face
389 if (face == null)
392 { 390 {
393 wearableCache = bakedModule.Get(sp.UUID); 391 // for some reason viewer is cleaning this
392 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
393 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
394 wearableCache[idx].CacheId = UUID.Zero;
395 wearableCache[idx].TextureID = UUID.Zero;
396 wearableCache[idx].TextureAsset = null;
397 continue;
394 } 398 }
395 catch (Exception) 399 else
396 { 400 {
401 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
402 {
403 wearableCache[idx].CacheId = UUID.Zero;
404 wearableCache[idx].TextureID = UUID.Zero;
405 wearableCache[idx].TextureAsset = null;
406 continue;
407 }
397 408
398 } 409/*
399 if (wearableCache != null) 410 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
400 {
401 for (int i = 0; i < wearableCache.Length; i++)
402 { 411 {
403 cache.Cache(wearableCache[i].TextureAsset); 412 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
413 {
414 wearableCache[idx].CacheId = cacheItems[i].CacheId;
415 validDirtyBakes++;
416
417 //assuming this can only happen if asset is in cache
418 }
419 hits++;
420 continue;
421 }
422*/
423 wearableCache[idx].TextureAsset = null;
424 if (cache != null)
425 wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString());
426
427 if (wearableCache[idx].TextureAsset != null)
428 {
429 if ( wearableCache[idx].TextureID != face.TextureID ||
430 wearableCache[idx].CacheId != cacheItems[i].CacheId)
431 validDirtyBakes++;
432
433 wearableCache[idx].TextureID = face.TextureID;
434 wearableCache[idx].CacheId = cacheItems[i].CacheId;
435 hits++;
436 }
437 else
438 {
439 wearableCache[idx].CacheId = UUID.Zero;
440 wearableCache[idx].TextureID = UUID.Zero;
441 wearableCache[idx].TextureAsset = null;
442 missing.Add(face.TextureID);
443 continue;
404 } 444 }
405 } 445 }
406 } 446 }
407 /* 447
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 448 sp.Appearance.WearableCacheItems = wearableCache;
409 if (invService.GetRootFolder(userID) != null) 449
450 if (missing.Count > 0)
410 { 451 {
411 WearableCacheItem[] wearableCache = null; 452 foreach (UUID id in missing)
412 if (bakedModule != null) 453 sp.ControllingClient.SendRebakeAvatarTextures(id);
454 }
455
456 if (validDirtyBakes > 0 && hits == cacheItems.Length)
457 {
458 // if we got a full set of baked textures save all in BakedTextureModule
459 if (m_BakedTextureModule != null)
413 { 460 {
414 try 461 m_log.Debug("[UpdateBakedCache] uploading to bakedModule cache");
462
463 m_BakedTextureModule.Store(sp.UUID, wearableCache);
464 }
465 }
466
467
468 // debug
469 m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString() + " rebakes " + missing.Count);
470/*
471 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
472 {
473 int j = AvatarAppearance.BAKE_INDICES[iter];
474 m_log.Debug("[UpdateBCache] {" + iter + "/" +
475 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
476 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
477 sp.Appearance.WearableCacheItems[j].TextureID);
478 }
479*/
480 return (hits == cacheItems.Length);
481 }
482
483 // called when we get a new root avatar
484 public bool ValidateBakedTextureCache(IScenePresence sp)
485 {
486 int hits = 0;
487
488 if (((ScenePresence)sp).isNPC)
489 return true;
490
491 lock (m_setAppearanceLock)
492 {
493 IAssetService cache = m_scene.AssetService;
494 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
495 WearableCacheItem[] bakedModuleCache = null;
496
497 if (cache == null)
498 return false;
499
500 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
501
502 // big debug
503 m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
504/*
505 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
506 {
507 int j = AvatarAppearance.BAKE_INDICES[iter];
508 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
509 if (wearableCache == null)
510 {
511 if (face != null)
512 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
513 else
514 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
515 }
516 else
517 {
518 if (face != null)
519 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
520 "}: cc-" +
521 wearableCache[j].CacheId + ", ct-" +
522 wearableCache[j].TextureID
523 );
524 else
525 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
526 "}: cc-" +
527 wearableCache[j].CacheId + ", ct-" +
528 wearableCache[j].TextureID
529 );
530 }
531 }
532*/
533 bool wearableCacheValid = false;
534 if (wearableCache == null)
535 {
536 wearableCache = WearableCacheItem.GetDefaultCacheItem();
537 }
538 else
539 {
540 // we may have received a full cache
541 // check same coerence and store
542 wearableCacheValid = true;
543 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 544 {
416 wearableCache = bakedModule.Get(userID); 545 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 546 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 547 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 548 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 549 if (face.TextureID == wearableCache[idx].TextureID &&
550 face.TextureID != UUID.Zero)
551 {
552 if (wearableCache[idx].TextureAsset != null)
553 {
554 hits++;
555 wearableCache[idx].TextureAsset.Temporary = true;
556 wearableCache[idx].TextureAsset.Local = true;
557 cache.Store(wearableCache[idx].TextureAsset);
558 continue;
559 }
560 if (cache.GetCached((wearableCache[idx].TextureID).ToString()) != null)
561 {
562 hits++;
563 continue;
564 }
565 }
566 wearableCacheValid = false;
422 } 567 }
423 } 568 }
424 catch (Exception) 569
570 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
571 if (wearableCacheValid)
572 m_log.Debug("[ValidateBakedCache] have valid local cache");
573 }
574
575 bool checkExternal = false;
576
577 if (!wearableCacheValid)
578 {
579 // only use external bake module on login condition check
580// ScenePresence ssp = null;
581// if (sp is ScenePresence)
425 { 582 {
426 583// ssp = (ScenePresence)sp;
584// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
585// bakedModule != null;
586
587 // or do it anytime we dont have the cache
588 checkExternal = bakedModule != null;
427 } 589 }
428 } 590 }
429 */
430 591
431 // Process the texture entry 592 if (checkExternal)
432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
433 {
434 int idx = AvatarAppearance.BAKE_INDICES[i];
435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
436
437 // No face, so lets check our baked service cache, teleport or login.
438 if (face == null)
439 { 593 {
440 if (wearableCache != null) 594 hits = 0;
595 bool gotbacked = false;
596
597 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
598 try
599 {
600 bakedModuleCache = bakedModule.Get(sp.UUID);
601 }
602 catch (Exception e)
441 { 603 {
442 // If we find the an appearance item, set it as the textureentry and the face 604 m_log.ErrorFormat(e.ToString());
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 605 bakedModuleCache = null;
444 if (searchitem != null) 606 }
607
608 if (bakedModuleCache != null)
609 {
610 m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
611
612 for (int i = 0; i < bakedModuleCache.Length; i++)
445 { 613 {
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 614 int j = (int)bakedModuleCache[i].TextureIndex;
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 615
448 face = sp.Appearance.Texture.FaceTextures[idx]; 616 if (bakedModuleCache[i].TextureAsset != null)
617 {
618 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
619 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
620 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
621 bakedModuleCache[i].TextureAsset.Temporary = true;
622 bakedModuleCache[i].TextureAsset.Local = true;
623 cache.Store(bakedModuleCache[i].TextureAsset);
624 }
449 } 625 }
450 else 626 gotbacked = true;
627 }
628
629 if (gotbacked)
630 {
631 // force the ones we got
632 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
451 { 633 {
452 // if there is no texture entry and no baked cache, skip it 634 int idx = AvatarAppearance.BAKE_INDICES[i];
635 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
636
637 if (sp.Appearance.Texture.FaceTextures[idx] == null)
638 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint)idx);
639 sp.Appearance.Texture.FaceTextures[idx].TextureID = wearableCache[idx].TextureID;
640 face = sp.Appearance.Texture.FaceTextures[idx];
641
642 // this should be removed
643 if (face.TextureID != UUID.Zero && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
644 hits++;
453 continue; 645 continue;
454 } 646 }
455 } 647 }
456 else
457 {
458 //No texture entry face and no cache. Skip this face.
459 continue;
460 }
461 } 648 }
462
463// m_log.DebugFormat(
464// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
465// face.TextureID, idx, client.Name, client.AgentId);
466 649
467 // if the texture is one of the "defaults" then skip it 650 sp.Appearance.WearableCacheItems = wearableCache;
468 // this should probably be more intelligent (skirt texture doesnt matter
469 // if the avatar isnt wearing a skirt) but if any of the main baked
470 // textures is default then the rest should be as well
471 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
472 continue;
473
474 defonly = false; // found a non-default texture reference
475 651
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 652 }
479 653
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 654 // debug
481 655 m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
482 // If we only found default textures, then the appearance is not cached 656/*
483 return (defonly ? false : true); 657 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
658 {
659 int j = AvatarAppearance.BAKE_INDICES[iter];
660 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
661 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
662 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
663 sp.Appearance.WearableCacheItems[j].TextureID);
664 }
665*/
666 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 667 }
485 668
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 669 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 670 {
671 if (((ScenePresence)sp).isNPC)
672 return 0;
673
488 int texturesRebaked = 0; 674 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 675// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
490 676
@@ -497,14 +683,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 683 if (face == null)
498 continue; 684 continue;
499 685
500// m_log.DebugFormat(
501// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
502// face.TextureID, idx, client.Name, client.AgentId);
503
504 // if the texture is one of the "defaults" then skip it
505 // this should probably be more intelligent (skirt texture doesnt matter
506 // if the avatar isnt wearing a skirt) but if any of the main baked
507 // textures is default then the rest should be as well
508 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 686 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 687 continue;
510 688
@@ -675,7 +853,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 853
676 if (invService.GetRootFolder(userID) != null) 854 if (invService.GetRootFolder(userID) != null)
677 { 855 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 856 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 857 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 858 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 859 {
@@ -1080,8 +1258,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1258
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1259 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1260 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1261 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1262 if (avatAppearance.Wearables.Length <= wear.Type)
1263 {
1264 int currentLength = avatAppearance.Wearables.Length;
1265 AvatarWearable[] wears = avatAppearance.Wearables;
1266 Array.Resize(ref wears, wear.Type + 1);
1267 for (int i = currentLength ; i <= wear.Type ; i++)
1268 wears[i] = new AvatarWearable();
1269 avatAppearance.Wearables = wears;
1270 }
1271 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1272 }
1086 1273
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1274 avatAppearance.GetAssetsFrom(sp.Appearance);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 9513408..dd93449 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
182 eyesFace.TextureID = eyesTextureId; 182 eyesFace.TextureID = eyesTextureId;
183 183
184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
185 afm.SaveBakedTextures(userId); 185 afm.SaveBakedTextures(userId);
186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
187 187
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 414f06a..c0686d9 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -101,8 +101,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
101 if (m_URL == String.Empty) 101 if (m_URL == String.Empty)
102 return null; 102 return null;
103 103
104 int size = 0;
105
106 using (RestClient rc = new RestClient(m_URL)) 104 using (RestClient rc = new RestClient(m_URL))
107 { 105 {
108 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 106 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -113,35 +111,34 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
113 111
114 try 112 try
115 { 113 {
116 Stream s = rc.Request(m_Auth); 114 using(Stream s = rc.Request(m_Auth))
117
118 using (XmlTextReader sr = new XmlTextReader(s))
119 { 115 {
120 sr.ReadStartElement("BakedAppearance"); 116 using(XmlTextReader sr = new XmlTextReader(s))
121 while (sr.LocalName == "BakedTexture")
122 { 117 {
123 string sTextureIndex = sr.GetAttribute("TextureIndex"); 118 sr.ReadStartElement("BakedAppearance");
124 int lTextureIndex = Convert.ToInt32(sTextureIndex); 119 while(sr.LocalName == "BakedTexture")
125 string sCacheId = sr.GetAttribute("CacheId");
126 UUID lCacheId = UUID.Zero;
127 if (!(UUID.TryParse(sCacheId, out lCacheId)))
128 { 120 {
121 string sTextureIndex = sr.GetAttribute("TextureIndex");
122 int lTextureIndex = Convert.ToInt32(sTextureIndex);
123 string sCacheId = sr.GetAttribute("CacheId");
124 UUID lCacheId = UUID.Zero;
125 if(!(UUID.TryParse(sCacheId,out lCacheId)))
126 {
129 // ?? Nothing here 127 // ?? Nothing here
128 }
129
130 sr.ReadStartElement("BakedTexture");
131 if(sr.Name=="AssetBase")
132 {
133 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
134 ret.Add(new WearableCacheItem() { CacheId = lCacheId,TextureIndex = (uint)lTextureIndex,TextureAsset = a,TextureID = a.FullID });
135 sr.ReadEndElement();
136 }
130 } 137 }
131 138 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}",ret.Count,id);
132 ++size;
133
134 sr.ReadStartElement("BakedTexture");
135 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
136 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
137
138 sr.ReadEndElement();
139 } 139 }
140 140 return ret.ToArray();
141 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
142 } 141 }
143
144 return ret.ToArray();
145 } 142 }
146 catch (XmlException) 143 catch (XmlException)
147 { 144 {
@@ -150,13 +147,22 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
150 } 147 }
151 } 148 }
152 149
150 public void Store(UUID agentId)
151 {
152 }
153
154 public void UpdateMeshAvatar(UUID agentId)
155 {
156 }
157
153 public void Store(UUID agentId, WearableCacheItem[] data) 158 public void Store(UUID agentId, WearableCacheItem[] data)
154 { 159 {
155 if (m_URL == String.Empty) 160 if (m_URL == String.Empty)
156 return; 161 return;
157 162
163 int numberWears = 0;
158 MemoryStream reqStream; 164 MemoryStream reqStream;
159 165
160 using (MemoryStream bakeStream = new MemoryStream()) 166 using (MemoryStream bakeStream = new MemoryStream())
161 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null)) 167 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
162 { 168 {
@@ -164,15 +170,16 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
164 170
165 for (int i = 0; i < data.Length; i++) 171 for (int i = 0; i < data.Length; i++)
166 { 172 {
167 if (data[i] != null) 173 if (data[i] != null && data[i].TextureAsset != null)
168 { 174 {
169 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 175 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
170 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 176 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
171 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 177 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
172 if (data[i].TextureAsset != null) 178// if (data[i].TextureAsset != null)
173 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 179 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
174 180
175 bakeWriter.WriteEndElement(); 181 bakeWriter.WriteEndElement();
182 numberWears++;
176 } 183 }
177 } 184 }
178 185
@@ -182,17 +189,18 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
182 reqStream = new MemoryStream(bakeStream.ToArray()); 189 reqStream = new MemoryStream(bakeStream.ToArray());
183 } 190 }
184 191
185 RestClient rc = new RestClient(m_URL);
186 rc.AddResourcePath("bakes");
187 rc.AddResourcePath(agentId.ToString());
188
189 rc.RequestMethod = "POST";
190
191 Util.FireAndForget( 192 Util.FireAndForget(
192 delegate 193 delegate
193 { 194 {
194 rc.Request(reqStream, m_Auth); 195 using(RestClient rc = new RestClient(m_URL))
195 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId); 196 {
197 rc.AddResourcePath("bakes");
198 rc.AddResourcePath(agentId.ToString());
199 rc.RequestMethod = "POST";
200
201 rc.Request(reqStream, m_Auth);
202 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId);
203 }
196 }, null, "XBakesModule.Store" 204 }, null, "XBakesModule.Store"
197 ); 205 );
198 } 206 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..d83713b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -51,7 +51,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
51 private int m_saydistance = 20; 51 private int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 private int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 private int m_whisperdistance = 10;
54 54 private List<Scene> m_scenes = new List<Scene>();
55 private List<string> FreezeCache = new List<string>();
56 private string m_adminPrefix = "";
55 internal object m_syncy = new object(); 57 internal object m_syncy = new object();
56 58
57 internal IConfig m_config; 59 internal IConfig m_config;
@@ -69,21 +71,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 71 m_enabled = false;
70 return; 72 return;
71 } 73 }
74
75 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
76 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
77 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
78 m_adminPrefix = m_config.GetString("admin_prefix", "");
72 } 79 }
73
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
77 } 80 }
78 81
79 public virtual void AddRegion(Scene scene) 82 public virtual void AddRegion(Scene scene)
80 { 83 {
81 if (!m_enabled) 84 if (!m_enabled) return;
82 return;
83 85
84 scene.EventManager.OnNewClient += OnNewClient; 86 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 87 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 88 if (!m_scenes.Contains(scene))
89 {
90 m_scenes.Add(scene);
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
93 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
94 }
95 }
87 96
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 97 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 98 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,12 +112,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 112
104 public virtual void RemoveRegion(Scene scene) 113 public virtual void RemoveRegion(Scene scene)
105 { 114 {
106 if (!m_enabled) 115 if (!m_enabled) return;
107 return;
108 116
109 scene.EventManager.OnNewClient -= OnNewClient; 117 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 118 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 119 if (m_scenes.Contains(scene))
120 {
121 scene.EventManager.OnNewClient -= OnNewClient;
122 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
123 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
124 m_scenes.Remove(scene);
125 }
126 }
112 } 127 }
113 128
114 public virtual void Close() 129 public virtual void Close()
@@ -165,7 +180,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 180 return;
166 } 181 }
167 182
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 183 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
184 {
185 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
186 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
187 }
188 else
189 {
190 DeliverChatToAvatars(ChatSourceType.Agent, c);
191 }
169 } 192 }
170 193
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 194 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,33 +202,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 202 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 203 {
181 string fromName = c.From; 204 string fromName = c.From;
205 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 206 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 207 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 208 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 209 IScene scene = c.Scene;
210 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 211 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 212 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 213
214 bool checkParcelHide = false;
215 UUID sourceParcelID = UUID.Zero;
216 Vector3 hidePos = fromPos;
217
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 218 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 219
192 switch (sourceType) 220 switch (sourceType)
193 { 221 {
194 case ChatSourceType.Agent: 222 case ChatSourceType.Agent:
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 223 if (!(scene is Scene))
224 {
225 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
226 scene.RegionInfo.RegionName, c.Sender.AgentId);
227 return;
228 }
229 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
196 fromPos = avatar.AbsolutePosition; 230 fromPos = avatar.AbsolutePosition;
197 fromName = avatar.Name; 231 fromName = avatar.Name;
198 fromID = c.Sender.AgentId; 232 fromID = c.Sender.AgentId;
233 if (avatar.GodLevel >= 200)
234 { // let gods speak to outside or things may get confusing
235 fromNamePrefix = m_adminPrefix;
236 checkParcelHide = false;
237 }
238 else
239 {
240 checkParcelHide = true;
241 }
242 destination = UUID.Zero; // Avatars cant "SayTo"
199 ownerID = c.Sender.AgentId; 243 ownerID = c.Sender.AgentId;
200 244
245 hidePos = fromPos;
201 break; 246 break;
202 247
203 case ChatSourceType.Object: 248 case ChatSourceType.Object:
204 fromID = c.SenderUUID; 249 fromID = c.SenderUUID;
205 250
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 251 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
252 {
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 253 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
208 254 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
255 {
256 checkParcelHide = true;
257 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
258 }
259 }
209 break; 260 break;
210 } 261 }
211 262
@@ -214,38 +265,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 265 message = message.Substring(0, 1000);
215 266
216// m_log.DebugFormat( 267// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 268// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 269// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 270
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 271 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 272
222 if (targetID == UUID.Zero) 273 if (checkParcelHide)
274 {
275 checkParcelHide = false;
276 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
277 {
278 ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y);
279 if (srcland != null && !srcland.LandData.SeeAVs)
280 {
281 sourceParcelID = srcland.LandData.GlobalID;
282 checkParcelHide = true;
283 }
284 }
285 }
286
287 foreach (Scene s in m_scenes)
223 { 288 {
224 // This should use ForEachClient, but clients don't have a position. 289 // This should use ForEachClient, but clients don't have a position.
225 // If camera is moved into client, then camera position can be used 290 // If camera is moved into client, then camera position can be used
226 scene.ForEachScenePresence( 291 // MT: No, it can't, as chat is heard from the avatar position, not
292 // the camera position.
293
294 s.ForEachScenePresence(
227 delegate(ScenePresence presence) 295 delegate(ScenePresence presence)
228 { 296 {
229 if (TrySendChatMessage( 297 if (destination != UUID.Zero && presence.UUID != destination)
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 298 return;
231 receiverIDs.Add(presence.UUID); 299 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
300 if (Presencecheck != null)
301 {
302 // This will pass all chat from objects. Not
303 // perfect, but it will do. For now. Better
304 // than the prior behavior of muting all
305 // objects on a parcel with access restrictions
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (destination != UUID.Zero)
314 {
315 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
316 receiverIDs.Add(presence.UUID);
317 }
318 else
319 {
320 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
321 receiverIDs.Add(presence.UUID);
322 }
323 }
324 }
232 } 325 }
233 ); 326 );
234 } 327 }
235 else 328
236 { 329 (scene as Scene).EventManager.TriggerOnChatToClients(
237 // This is a send to a specific client eg from llRegionSayTo
238 // no need to check distance etc, jand send is as say
239 ScenePresence presence = scene.GetScenePresence(targetID);
240 if (presence != null && !presence.IsChildAgent)
241 {
242 if (TrySendChatMessage(
243 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
244 receiverIDs.Add(presence.UUID);
245 }
246 }
247
248 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 330 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 331 }
251 332
@@ -287,28 +368,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
287 } 368 }
288 369
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 370 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 371 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292 372
293 ((Scene)c.Scene).ForEachRootClient( 373 if (c.Scene != null)
294 delegate(IClientAPI client) 374 {
295 { 375 ((Scene)c.Scene).ForEachRootClient
296 // don't forward SayOwner chat from objects to 376 (
297 // non-owner agents 377 delegate(IClientAPI client)
298 if ((c.Type == ChatTypeEnum.Owner) && 378 {
299 (null != c.SenderObject) && 379 // don't forward SayOwner chat from objects to
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 380 // non-owner agents
301 return; 381 if ((c.Type == ChatTypeEnum.Owner) &&
302 382 (null != c.SenderObject) &&
303 client.SendChatMessage( 383 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 384 return;
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 385
306 386 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
307 receiverIDs.Add(client.AgentId); 387 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
308 }); 388 receiverIDs.Add(client.AgentId);
309 389 }
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 390 );
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 391 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
392 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
393 }
312 } 394 }
313 395
314 /// <summary> 396 /// <summary>
@@ -360,6 +442,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
360 return true; 442 return true;
361 } 443 }
362 444
445 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
446 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
447 {
448 System.Threading.Timer Timer;
449 if (flags == 0)
450 {
451 FreezeCache.Add(target.ToString());
452 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
453 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
454 Timers.Add(target, Timer);
455 }
456 else
457 {
458 FreezeCache.Remove(target.ToString());
459 Timers.TryGetValue(target, out Timer);
460 Timers.Remove(target);
461 Timer.Dispose();
462 }
463 }
464
465 private void OnEndParcelFrozen(object avatar)
466 {
467 UUID target = (UUID)avatar;
468 FreezeCache.Remove(target.ToString());
469 System.Threading.Timer Timer;
470 Timers.TryGetValue(target, out Timer);
471 Timers.Remove(target);
472 Timer.Dispose();
473 }
363 #region SimulatorFeaturesRequest 474 #region SimulatorFeaturesRequest
364 475
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 476 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index fc23b72..4e1958a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -183,10 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
183 try 183 try
184 { 184 {
185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
186
187 if (obj == null) 186 if (obj == null)
188 return; 187 return;
189
190 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0 188 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
191 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage) 189 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
192 { 190 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index a896897..56819fa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -203,8 +203,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
203 { 203 {
204 m_scene.ForEachRootClient(delegate(IClientAPI client) 204 m_scene.ForEachRootClient(delegate(IClientAPI client)
205 { 205 {
206 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName, 206 client.SendAgentAlertMessage(
207 message); 207 message, false);
208 }); 208 });
209 } 209 }
210 210
@@ -260,4 +260,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
260 return result; 260 return result;
261 } 261 }
262 } 262 }
263} \ No newline at end of file 263}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 08e7dd2..d6c4d5b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -262,6 +262,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
262 client.OnDenyFriendRequest += OnDenyFriendRequest; 262 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship; 263 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights; 264 client.OnGrantUserRights += GrantRights;
265 client.OnFindAgent += FindFriend;
265 266
266 // We need to cache information for child agents as well as root agents so that friend edit/move/delete 267 // We need to cache information for child agents as well as root agents so that friend edit/move/delete
267 // permissions will work across borders where both regions are on different simulators. 268 // permissions will work across borders where both regions are on different simulators.
@@ -726,6 +727,64 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
726 } 727 }
727 } 728 }
728 729
730 public void FindFriend(IClientAPI remoteClient,UUID HunterID ,UUID PreyID)
731 {
732 UUID requester = remoteClient.AgentId;
733 if(requester != HunterID) // only allow client agent to be the hunter (?)
734 return;
735
736 FriendInfo[] friends = GetFriendsFromCache(requester);
737 if (friends.Length == 0)
738 return;
739
740 FriendInfo friend = GetFriend(friends, PreyID);
741 if (friend == null)
742 return;
743
744 if((friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
745 return;
746
747 Scene hunterScene = (Scene)remoteClient.Scene;
748
749 if(hunterScene == null)
750 return;
751
752 // check local
753 ScenePresence sp;
754 double px;
755 double py;
756 if(hunterScene.TryGetScenePresence(PreyID, out sp))
757 {
758 if(sp == null)
759 return;
760 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
761 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
762
763 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
764 return;
765 }
766
767 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() });
768
769 if (friendSessions == null || friendSessions.Length == 0)
770 return;
771
772 PresenceInfo friendSession = friendSessions[0];
773 if (friendSession == null)
774 return;
775
776 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
777
778 if(region == null)
779 return;
780
781 // we don't have presence location so point to a standard region center for now
782 px = region.RegionLocX + 128.0;
783 py = region.RegionLocY + 128.0;
784
785 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
786 }
787
729 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) 788 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
730 { 789 {
731 UUID requester = remoteClient.AgentId; 790 UUID requester = remoteClient.AgentId;
@@ -745,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
745 804
746 if (friend != null) // Found it 805 if (friend != null) // Found it
747 { 806 {
748 // Store it on the DB 807 // Store it on service
749 if (!StoreRights(requester, friendID, rights)) 808 if (!StoreRights(requester, friendID, rights))
750 { 809 {
751 remoteClient.SendAlertMessage("Unable to grant rights."); 810 remoteClient.SendAlertMessage("Unable to grant rights.");
@@ -869,28 +928,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
869 return false; 928 return false;
870 } 929 }
871 930
872 public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights) 931 public bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
873 { 932 {
874 IClientAPI friendClient = LocateClientObject(friendID); 933 IClientAPI friendClient = LocateClientObject(friendID);
875 if (friendClient != null) 934 if (friendClient != null)
876 { 935 {
877 bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0; 936 int changedRights = newRights ^ oldRights;
937 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
878 if (onlineBitChanged) 938 if (onlineBitChanged)
879 { 939 {
880 if ((rights & (int)FriendRights.CanSeeOnline) == 1) 940 if ((newRights & (int)FriendRights.CanSeeOnline) == 1)
881 friendClient.SendAgentOnline(new UUID[] { userID }); 941 friendClient.SendAgentOnline(new UUID[] { userID });
882 else 942 else
883 friendClient.SendAgentOffline(new UUID[] { userID }); 943 friendClient.SendAgentOffline(new UUID[] { userID });
884 } 944 }
885 else 945
886 { 946 if(changedRights != 0)
887 bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; 947 friendClient.SendChangeUserRights(userID, friendID, newRights);
888 if (canEditObjectsChanged)
889 friendClient.SendChangeUserRights(userID, friendID, rights);
890 }
891 948
892 // Update local cache 949 // Update local cache
893 UpdateLocalCache(userID, friendID, rights); 950 UpdateLocalCache(userID, friendID, newRights);
894 951
895 return true; 952 return true;
896 } 953 }
@@ -946,8 +1003,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
946 lock (m_Friends) 1003 lock (m_Friends)
947 { 1004 {
948 FriendInfo[] friends = GetFriendsFromCache(friendID); 1005 FriendInfo[] friends = GetFriendsFromCache(friendID);
949 FriendInfo finfo = GetFriend(friends, userID); 1006 if(friends != EMPTY_FRIENDS)
950 finfo.TheirFlags = rights; 1007 {
1008 FriendInfo finfo = GetFriend(friends, userID);
1009 if(finfo!= null)
1010 finfo.TheirFlags = rights;
1011 }
951 } 1012 }
952 } 1013 }
953 1014
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 13512a2..c421740 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
211 { 211 {
212 UUID fromID = UUID.Zero; 212 UUID fromID = UUID.Zero;
213 UUID toID = UUID.Zero; 213 UUID toID = UUID.Zero;
214 int rights = 0, userFlags = 0; 214 int oldRights = 0, newRights = 0;
215 215
216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) 216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
217 return FailureResult(); 217 return FailureResult();
@@ -222,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
222 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 222 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
223 return FailureResult(); 223 return FailureResult();
224 224
225 if (!Int32.TryParse(request["UserFlags"].ToString(), out userFlags)) 225 if (!Int32.TryParse(request["UserFlags"].ToString(), out oldRights))
226 return FailureResult(); 226 return FailureResult();
227 227
228 if (!Int32.TryParse(request["Rights"].ToString(), out rights)) 228 if (!Int32.TryParse(request["Rights"].ToString(), out newRights))
229 return FailureResult(); 229 return FailureResult();
230 230
231 if (m_FriendsModule.LocalGrantRights(UUID.Zero, UUID.Zero, userFlags, rights)) 231 if (m_FriendsModule.LocalGrantRights(fromID, toID, oldRights, newRights))
232 return SuccessResult(); 232 return SuccessResult();
233 233
234 return FailureResult(); 234 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 3b6d970..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -49,6 +49,8 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
49using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51 51
52using Mono.Addins;
53
52namespace OpenSim.Region.CoreModules.Avatar.Gods 54namespace OpenSim.Region.CoreModules.Avatar.Gods
53{ 55{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
@@ -62,6 +64,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
62 64
63 protected Scene m_scene; 65 protected Scene m_scene;
64 protected IDialogModule m_dialogModule; 66 protected IDialogModule m_dialogModule;
67
65 protected IDialogModule DialogModule 68 protected IDialogModule DialogModule
66 { 69 {
67 get 70 get
@@ -146,6 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 UUID godSessionID = userData["GodSessionID"].AsUUID(); 149 UUID godSessionID = userData["GodSessionID"].AsUUID();
147 uint kickFlags = userData["KickFlags"].AsUInteger(); 150 uint kickFlags = userData["KickFlags"].AsUInteger();
148 string reason = userData["Reason"].AsString(); 151 string reason = userData["Reason"].AsString();
152
149 ScenePresence god = m_scene.GetScenePresence(godID); 153 ScenePresence god = m_scene.GetScenePresence(godID);
150 if (god == null || god.ControllingClient.SessionId != godSessionID) 154 if (god == null || god.ControllingClient.SessionId != godSessionID)
151 return String.Empty; 155 return String.Empty;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..55e30a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Mono.Addins; 32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
@@ -44,6 +45,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
44 private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
46 47
48 private Timer m_logTimer = new Timer(10000);
49 private List<GridInstantMessage> m_logData = new List<GridInstantMessage>();
50 private string m_restUrl;
51
47 /// <value> 52 /// <value>
48 /// Is this module enabled? 53 /// Is this module enabled?
49 /// </value> 54 /// </value>
@@ -63,9 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
63 "InstantMessageModule", "InstantMessageModule") != 68 "InstantMessageModule", "InstantMessageModule") !=
64 "InstantMessageModule") 69 "InstantMessageModule")
65 return; 70 return;
71 m_restUrl = config.Configs["Messaging"].GetString("LogURL", String.Empty);
66 } 72 }
67 73
68 m_enabled = true; 74 m_enabled = true;
75 m_logTimer.AutoReset = false;
76 m_logTimer.Elapsed += LogTimerElapsed;
69 } 77 }
70 78
71 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
@@ -150,6 +158,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
150 { 158 {
151 byte dialog = im.dialog; 159 byte dialog = im.dialog;
152 160
161 if (client != null && dialog == (byte)InstantMessageDialog.MessageFromAgent)
162 LogInstantMesssage(im);
163
153 if (dialog != (byte)InstantMessageDialog.MessageFromAgent 164 if (dialog != (byte)InstantMessageDialog.MessageFromAgent
154 && dialog != (byte)InstantMessageDialog.StartTyping 165 && dialog != (byte)InstantMessageDialog.StartTyping
155 && dialog != (byte)InstantMessageDialog.StopTyping 166 && dialog != (byte)InstantMessageDialog.StopTyping
@@ -159,6 +170,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 170 return;
160 } 171 }
161 172
173 //DateTime dt = DateTime.UtcNow;
174
175 // Ticks from UtcNow, but make it look like local. Evil, huh?
176 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
177
178 //try
179 //{
180 // // Convert that to the PST timezone
181 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
182 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
183 //}
184 //catch
185 //{
186 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
187 //}
188
189 //// And make it look local again to fool the unix time util
190 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
191
192 // If client is null, this message comes from storage and IS offline
193 if (client != null)
194 im.offline = 0;
195
196 if (im.offline == 0)
197 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
198
162 if (m_TransferModule != null) 199 if (m_TransferModule != null)
163 { 200 {
164 if (client != null) 201 if (client != null)
@@ -202,5 +239,35 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
202 // 239 //
203 OnInstantMessage(null, msg); 240 OnInstantMessage(null, msg);
204 } 241 }
242
243 private void LogInstantMesssage(GridInstantMessage im)
244 {
245 if (m_logData.Count < 20)
246 {
247 // Restart the log write timer
248 m_logTimer.Stop();
249 }
250 if (!m_logTimer.Enabled)
251 m_logTimer.Start();
252
253 lock (m_logData)
254 {
255 m_logData.Add(im);
256 }
257 }
258
259 private void LogTimerElapsed(object source, ElapsedEventArgs e)
260 {
261 lock (m_logData)
262 {
263 if (m_restUrl != String.Empty && m_logData.Count > 0)
264 {
265 bool success = SynchronousRestObjectRequester.MakeRequest<List<GridInstantMessage>, bool>("POST", m_restUrl + "/LogMessages/", m_logData);
266 if (!success)
267 m_log.ErrorFormat("[INSTANT MESSAGE]: Failed to save log data");
268 }
269 m_logData.Clear();
270 }
271 }
205 } 272 }
206} 273}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..3c82fd9 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
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 bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,6 +139,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
138 // Try root avatar only first 145 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 146 foreach (Scene scene in m_Scenes)
140 { 147 {
@@ -181,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
181 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
182 } 189 }
183 190
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 191 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 192 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 193 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 194
@@ -249,6 +256,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 256 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 257 && requestData.ContainsKey("binary_bucket"))
251 { 258 {
259 if (m_MessageKey != String.Empty)
260 {
261 XmlRpcResponse error_resp = new XmlRpcResponse();
262 Hashtable error_respdata = new Hashtable();
263 error_respdata["success"] = "FALSE";
264 error_resp.Value = error_respdata;
265
266 if (!requestData.Contains("message_key"))
267 return error_resp;
268 if (m_MessageKey != (string)requestData["message_key"])
269 return error_resp;
270 }
271
252 // Do the easy way of validating the UUIDs 272 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 273 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 274 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -425,104 +445,192 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 445 return resp;
426 } 446 }
427 447
448
428 /// <summary> 449 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 450 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 451 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 452 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
453
454 private class GIM {
455 public GridInstantMessage im;
456 public MessageResultNotification result;
457 };
458
459 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
460 private int numInstantMessageThreads = 0;
432 461
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 462 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 463 {
435 GridInstantMessageDelegate icon = 464 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 465 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 466 GIM gim = new GIM();
467 gim.im = im;
468 gim.result = result;
469 pendingInstantMessages.Enqueue(gim);
470 } else {
471 ++ numInstantMessageThreads;
472 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
473 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
475 }
476 }
438 } 477 }
439 478
440 479
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 480 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 481 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 482 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 483 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 484 }
447 485
448 /// <summary> 486 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 487 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 488 /// </summary>
451 /// <remarks> 489
452 /// This is called from within a dedicated thread. 490 /// <param name="prevRegionHandle">
453 /// </remarks> 491 /// Pass in 0 the first time this method is called. It will be called recursively with the last
454 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) 492 /// regionhandle tried
493 /// </param>
494 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
455 { 495 {
496 GIM gim;
497 do {
498 try {
499 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
500 } catch (Exception e) {
501 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
502 }
503 lock (pendingInstantMessages) {
504 if (pendingInstantMessages.Count > 0) {
505 gim = pendingInstantMessages.Dequeue();
506 im = gim.im;
507 result = gim.result;
508 } else {
509 gim = null;
510 -- numInstantMessageThreads;
511 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
512 }
513 }
514 } while (gim != null);
515 }
516
517 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
518 {
519
456 UUID toAgentID = new UUID(im.toAgentID); 520 UUID toAgentID = new UUID(im.toAgentID);
521 PresenceInfo upd = null;
457 UUID regionID; 522 UUID regionID;
458 bool needToLookupAgent; 523 bool lookupAgent = false;
459 524
460 lock (m_UserRegionMap) 525 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 526 {
465 if (needToLookupAgent) 527 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 528 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 529 upd = new PresenceInfo();
530 upd.RegionID = m_UserRegionMap[toAgentID];
468 531
469 UUID foundRegionID = UUID.Zero; 532 // We need to compare the current regionhandle with the previous region handle
470 533 // or the recursive loop will never end because it will never try to lookup the agent again
471 if (presences != null) 534 if (prevRegionID == upd.RegionID)
472 { 535 {
473 foreach (PresenceInfo p in presences) 536 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 537 }
482
483 // If not found or the found region is the same as the last lookup, then message is undeliverable
484 if (foundRegionID == UUID.Zero || foundRegionID == regionID)
485 break;
486 else
487 regionID = foundRegionID;
488 } 538 }
489 539 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 540 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 541 lookupAgent = true;
494 break;
495 } 542 }
543 }
496 544
497 // Try to send the message to the agent via the retrieved region.
498 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
499 msgdata["region_handle"] = 0;
500 bool imresult = doIMSending(reginfo, msgdata);
501 545
502 // If the message delivery was successful, then cache the entry. 546 // Are we needing to look-up an agent?
503 if (imresult) 547 if (lookupAgent)
548 {
549 // Non-cached user agent lookup.
550 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
551 if (presences != null && presences.Length > 0)
504 { 552 {
505 lock (m_UserRegionMap) 553 foreach (PresenceInfo p in presences)
506 { 554 {
507 m_UserRegionMap[toAgentID] = regionID; 555 if (p.RegionID != UUID.Zero)
556 {
557 upd = p;
558 break;
559 }
508 } 560 }
509 result(true);
510 return;
511 } 561 }
512 562
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 563 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 564 {
515 // the presence service. 565 // check if we've tried this before..
516 needToLookupAgent = true; 566 // This is one way to end the recursive loop
567 //
568 if (upd.RegionID == prevRegionID)
569 {
570 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
571 HandleUndeliverableMessage(im, result);
572 return;
573 }
574 }
575 else
576 {
577 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
578 HandleUndeliverableMessage(im, result);
579 return;
580 }
517 } 581 }
518 582
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 583 if (upd != null)
520 // signal the delivery failure. 584 {
521 lock (m_UserRegionMap) 585 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 586 upd.RegionID);
587 if (reginfo != null)
588 {
589 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
590 // Not actually used anymore, left in for compatibility
591 // Remove at next interface change
592 //
593 msgdata["region_handle"] = 0;
594 bool imresult = doIMSending(reginfo, msgdata);
595 if (imresult)
596 {
597 // IM delivery successful, so store the Agent's location in our local cache.
598 lock (m_UserRegionMap)
599 {
600 if (m_UserRegionMap.ContainsKey(toAgentID))
601 {
602 m_UserRegionMap[toAgentID] = upd.RegionID;
603 }
604 else
605 {
606 m_UserRegionMap.Add(toAgentID, upd.RegionID);
607 }
608 }
609 result(true);
610 }
611 else
612 {
613 // try again, but lookup user this time.
614 // Warning, this must call the Async version
615 // of this method or we'll be making thousands of threads
616 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
617 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 618
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 619 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 620 SendGridInstantMessageViaXMLRPCAsync(im, result,
621 upd.RegionID);
622 }
623 }
624 else
625 {
626 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
627 HandleUndeliverableMessage(im, result);
628 }
629 }
630 else
631 {
632 HandleUndeliverableMessage(im, result);
633 }
526 } 634 }
527 635
528 /// <summary> 636 /// <summary>
@@ -622,8 +730,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey != String.Empty)
734 gim["message_key"] = m_MessageKey;
625 return gim; 735 return gim;
626 } 736 }
627
628 } 737 }
629} 738}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..369d480 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,6 +39,13 @@ using OpenSim.Region.Framework.Scenes;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 41{
42 public struct SendReply
43 {
44 public bool Success;
45 public string Message;
46 public int Disposition;
47 }
48
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
43 public class OfflineMessageModule : ISharedRegionModule 50 public class OfflineMessageModule : ISharedRegionModule
44 { 51 {
@@ -49,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
49 private string m_RestURL = String.Empty; 56 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null; 57 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true; 58 private bool m_ForwardOfflineGroupMessages = true;
59 private Dictionary<IClientAPI, List<UUID>> m_repliesSent= new Dictionary<IClientAPI, List<UUID>>();
52 60
53 public void Initialise(IConfigSource config) 61 public void Initialise(IConfigSource config)
54 { 62 {
@@ -168,11 +176,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 private void OnNewClient(IClientAPI client) 176 private void OnNewClient(IClientAPI client)
169 { 177 {
170 client.OnRetrieveInstantMessages += RetrieveInstantMessages; 178 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
179 client.OnLogout += OnClientLoggedOut;
180 }
181
182 public void OnClientLoggedOut(IClientAPI client)
183 {
184 m_repliesSent.Remove(client);
171 } 185 }
172 186
173 private void RetrieveInstantMessages(IClientAPI client) 187 private void RetrieveInstantMessages(IClientAPI client)
174 { 188 {
175 if (m_RestURL != "") 189 if (m_RestURL == String.Empty)
190 {
191 return;
192 }
193 else
176 { 194 {
177 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 195 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
178 196
@@ -180,28 +198,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
180 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 198 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 199 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
182 200
183 if (msglist == null) 201 if (msglist != null)
184 { 202 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 203 foreach (GridInstantMessage im in msglist)
186 return;
187 }
188
189 foreach (GridInstantMessage im in msglist)
190 {
191 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
192 // send it directly or else the item will be given twice
193 client.SendInstantMessage(im);
194 else
195 { 204 {
196 // Send through scene event manager so all modules get a chance 205 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
197 // to look at this message before it gets delivered. 206 // send it directly or else the item will be given twice
198 // 207 client.SendInstantMessage(im);
199 // Needed for proper state management for stored group 208 else
200 // invitations 209 {
201 // 210 // Send through scene event manager so all modules get a chance
202 Scene s = FindScene(client.AgentId); 211 // to look at this message before it gets delivered.
203 if (s != null) 212 //
204 s.EventManager.TriggerIncomingInstantMessage(im); 213 // Needed for proper state management for stored group
214 // invitations
215 //
216
217 im.offline = 1;
218
219 Scene s = FindScene(client.AgentId);
220 if (s != null)
221 s.EventManager.TriggerIncomingInstantMessage(im);
222 }
205 } 223 }
206 } 224 }
207 } 225 }
@@ -213,7 +231,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
213 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 231 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
214 im.dialog != (byte)InstantMessageDialog.GroupNotice && 232 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
215 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 233 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
216 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 234 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
235 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
217 { 236 {
218 return; 237 return;
219 } 238 }
@@ -225,15 +244,60 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
225 return; 244 return;
226 } 245 }
227 246
247 Scene scene = FindScene(new UUID(im.fromAgentID));
248 if (scene == null)
249 scene = m_SceneList[0];
250
251// Avination new code
252// SendReply reply = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, SendReply>(
253// "POST", m_RestURL+"/SaveMessage/?scope=" +
254// scene.RegionInfo.ScopeID.ToString(), im);
255
256// current opensim and osgrid compatible
228 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 257 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
229 "POST", m_RestURL+"/SaveMessage/", im, 10000); 258 "POST", m_RestURL+"/SaveMessage/", im, 10000);
259// current opensim and osgrid compatible end
230 260
231 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 261 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
232 { 262 {
233 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 263 IClientAPI client = FindClient(new UUID(im.fromAgentID));
234 if (client == null) 264 if (client == null)
235 return; 265 return;
266/* Avination new code
267 if (reply.Message == String.Empty)
268 reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
269
270 bool sendReply = true;
271
272 switch (reply.Disposition)
273 {
274 case 0: // Normal
275 break;
276 case 1: // Only once per user
277 if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
278 {
279 sendReply = false;
280 }
281 else
282 {
283 if (!m_repliesSent.ContainsKey(client))
284 m_repliesSent[client] = new List<UUID>();
285 m_repliesSent[client].Add(new UUID(im.toAgentID));
286 }
287 break;
288 }
236 289
290 if (sendReply)
291 {
292 client.SendInstantMessage(new GridInstantMessage(
293 null, new UUID(im.toAgentID),
294 "System", new UUID(im.fromAgentID),
295 (byte)InstantMessageDialog.MessageFromAgent,
296 reply.Message,
297 false, new Vector3()));
298 }
299*/
300// current opensim and osgrid compatible
237 client.SendInstantMessage(new GridInstantMessage( 301 client.SendInstantMessage(new GridInstantMessage(
238 null, new UUID(im.toAgentID), 302 null, new UUID(im.toAgentID),
239 "System", new UUID(im.fromAgentID), 303 "System", new UUID(im.fromAgentID),
@@ -241,6 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
241 "User is not logged in. "+ 305 "User is not logged in. "+
242 (success ? "Message saved." : "Message not saved"), 306 (success ? "Message saved." : "Message not saved"),
243 false, new Vector3())); 307 false, new Vector3()));
308// current opensim and osgrid compatible end
244 } 309 }
245 } 310 }
246 } 311 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 8847414..8d11d20 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -565,6 +565,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
565 return null; 565 return null;
566 } 566 }
567 567
568 return account;
569 /*
568 try 570 try
569 { 571 {
570 string encpass = Util.Md5Hash(pass); 572 string encpass = Util.Md5Hash(pass);
@@ -585,6 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
585 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e); 587 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
586 return null; 588 return null;
587 } 589 }
590 */
588 } 591 }
589 592
590 /// <summary> 593 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bba48cc..085328c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -165,8 +165,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
165 if (im.binaryBucket.Length < 17) // Invalid 165 if (im.binaryBucket.Length < 17) // Invalid
166 return; 166 return;
167 167
168 UUID receipientID = new UUID(im.toAgentID); 168 UUID recipientID = new UUID(im.toAgentID);
169 ScenePresence user = scene.GetScenePresence(receipientID); 169 ScenePresence user = scene.GetScenePresence(recipientID);
170 UUID copyID; 170 UUID copyID;
171 171
172 // First byte is the asset type 172 // First byte is the asset type
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
181 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
182 182
183 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
184 = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(client, recipientID, client.AgentId, folderID, UUID.Zero);
185 185
186 if (folderCopy == null) 186 if (folderCopy == null)
187 { 187 {
@@ -239,6 +239,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
239 im.imSessionID = copyID.Guid; 239 im.imSessionID = copyID.Guid;
240 } 240 }
241 241
242 im.offline = 0;
243
242 // Send the IM to the recipient. The item is already 244 // Send the IM to the recipient. The item is already
243 // in their inventory, so it will not be lost if 245 // in their inventory, so it will not be lost if
244 // they are offline. 246 // they are offline.
@@ -258,8 +260,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
258 }); 260 });
259 } 261 }
260 } 262 }
261 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 263 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
264 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
262 { 265 {
266 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
267 IInventoryService invService = scene.InventoryService;
268
269 // Special case: folder redirect.
270 // RLV uses this
271 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
272 {
273 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, client.AgentId);
274 folder = invService.GetFolder(folder);
275
276 if (folder != null)
277 {
278 if (im.binaryBucket.Length >= 16)
279 {
280 UUID destFolderID = new UUID(im.binaryBucket, 0);
281 if (destFolderID != UUID.Zero)
282 {
283 InventoryFolderBase destFolder = new InventoryFolderBase(destFolderID, client.AgentId);
284 destFolder = invService.GetFolder(destFolder);
285 if (destFolder != null)
286 {
287 if (folder.ParentID != destFolder.ID)
288 {
289 folder.ParentID = destFolder.ID;
290 invService.MoveFolder(folder);
291 client.SendBulkUpdateInventory(folder);
292 }
293 }
294 }
295 }
296 }
297 }
298
263 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 299 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
264 300
265 if (user != null) // Local 301 if (user != null) // Local
@@ -269,27 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
269 else 305 else
270 { 306 {
271 if (m_TransferModule != null) 307 if (m_TransferModule != null)
272 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 308 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
273
274 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
275 // and is apparently supposed to fix bulk inventory updates after accepting items. But
276 // instead it appears to cause two copies of an accepted folder for the receiving user in
277 // at least some cases. Folder/item update is already done when the offer is made (see code above)
278
279// // Send BulkUpdateInventory
280// IInventoryService invService = scene.InventoryService;
281// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
282//
283// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
284// folder = invService.GetFolder(folder);
285//
286// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
287//
288// // If the user has left the scene by the time the message comes back then we can't send
289// // them the update.
290// if (fromUser != null)
291// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
292 });
293 } 309 }
294 } 310 }
295 311
@@ -402,6 +418,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
402 previousParentFolderID = folder.ParentID; 418 previousParentFolderID = folder.ParentID;
403 folder.ParentID = trashFolder.ID; 419 folder.ParentID = trashFolder.ID;
404 invService.MoveFolder(folder); 420 invService.MoveFolder(folder);
421 client.SendBulkUpdateInventory(folder);
405 } 422 }
406 } 423 }
407 424
@@ -453,18 +470,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
453 /// <param name="im"></param> 470 /// <param name="im"></param>
454 private void OnGridInstantMessage(GridInstantMessage im) 471 private void OnGridInstantMessage(GridInstantMessage im)
455 { 472 {
456 // Check if it's a type of message that we should handle
457 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
458 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
459 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
460 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
461 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
462 return;
463
464 m_log.DebugFormat(
465 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
466 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
467
468 // Check if this is ours to handle 473 // Check if this is ours to handle
469 // 474 //
470 Scene scene = FindClientScene(new UUID(im.toAgentID)); 475 Scene scene = FindClientScene(new UUID(im.toAgentID));
@@ -475,32 +480,100 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
475 // Find agent to deliver to 480 // Find agent to deliver to
476 // 481 //
477 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 482 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
483 if (user == null)
484 return;
478 485
479 if (user != null) 486 // This requires a little bit of processing because we have to make the
487 // new item visible in the recipient's inventory here
488 //
489 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
480 { 490 {
481 user.ControllingClient.SendInstantMessage(im); 491 if (im.binaryBucket.Length < 17) // Invalid
492 return;
493
494 UUID recipientID = new UUID(im.toAgentID);
482 495
483 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 496 // First byte is the asset type
484 { 497 AssetType assetType = (AssetType)im.binaryBucket[0];
485 AssetType assetType = (AssetType)im.binaryBucket[0];
486 UUID inventoryID = new UUID(im.binaryBucket, 1);
487 498
488 IInventoryService invService = scene.InventoryService; 499 if (AssetType.Folder == assetType)
489 InventoryNodeBase node = null; 500 {
490 if (AssetType.Folder == assetType) 501 UUID folderID = new UUID(im.binaryBucket, 1);
502
503 InventoryFolderBase given =
504 new InventoryFolderBase(folderID, recipientID);
505 InventoryFolderBase folder =
506 scene.InventoryService.GetFolder(given);
507
508 if (folder != null)
509 user.ControllingClient.SendBulkUpdateInventory(folder);
510 }
511 else
512 {
513 UUID itemID = new UUID(im.binaryBucket, 1);
514
515 InventoryItemBase given =
516 new InventoryItemBase(itemID, recipientID);
517 InventoryItemBase item =
518 scene.InventoryService.GetItem(given);
519
520 if (item != null)
491 { 521 {
492 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); 522 user.ControllingClient.SendBulkUpdateInventory(item);
493 node = invService.GetFolder(folder);
494 } 523 }
495 else 524 }
525 user.ControllingClient.SendInstantMessage(im);
526 }
527 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
528 {
529 if (im.binaryBucket.Length < 1) // Invalid
530 return;
531
532 UUID recipientID = new UUID(im.toAgentID);
533
534 // Bucket is the asset type
535 AssetType assetType = (AssetType)im.binaryBucket[0];
536
537 if (AssetType.Folder == assetType)
538 {
539 UUID folderID = new UUID(im.imSessionID);
540
541 InventoryFolderBase given =
542 new InventoryFolderBase(folderID, recipientID);
543 InventoryFolderBase folder =
544 scene.InventoryService.GetFolder(given);
545
546 if (folder != null)
547 user.ControllingClient.SendBulkUpdateInventory(folder);
548 }
549 else
550 {
551 UUID itemID = new UUID(im.imSessionID);
552
553 InventoryItemBase given =
554 new InventoryItemBase(itemID, recipientID);
555 InventoryItemBase item =
556 scene.InventoryService.GetItem(given);
557
558 if (item != null)
496 { 559 {
497 InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); 560 user.ControllingClient.SendBulkUpdateInventory(item);
498 node = invService.GetItem(item);
499 } 561 }
500
501 if (node != null)
502 user.ControllingClient.SendBulkUpdateInventory(node);
503 } 562 }
563
564 // Fix up binary bucket since this may be 17 chars long here
565 Byte[] bucket = new Byte[1];
566 bucket[0] = im.binaryBucket[0];
567 im.binaryBucket = bucket;
568
569 user.ControllingClient.SendInstantMessage(im);
570 }
571 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
572 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
573 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
574 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
575 {
576 user.ControllingClient.SendInstantMessage(im);
504 } 577 }
505 } 578 }
506 } 579 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 465ffbc..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -163,16 +163,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
163 scene.RegionInfo.RegionHandle, 163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X, 164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z)); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 170 GridInstantMessage m;
171 client.FirstName+" "+client.LastName, targetid, 171
172 (byte)InstantMessageDialog.RequestTeleport, false, 172 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
173 message, dest, false, presence.AbsolutePosition, 173 {
174 new Byte[0], true); 174 m = new GridInstantMessage(scene, client.AgentId,
175 175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0], true);
179 }
180 else
181 {
182 m = new GridInstantMessage(scene, client.AgentId,
183 client.FirstName+" "+client.LastName, targetid,
184 (byte)InstantMessageDialog.RequestTeleport, false,
185 message, dest, false, presence.AbsolutePosition,
186 new Byte[0], true);
187 }
188
176 if (m_TransferModule != null) 189 if (m_TransferModule != null)
177 { 190 {
178 m_TransferModule.SendInstantMessage(m, 191 m_TransferModule.SendInstantMessage(m,
@@ -207,7 +220,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
207 { 220 {
208 // Forward remote teleport requests 221 // Forward remote teleport requests
209 // 222 //
210 if (msg.dialog != 22) 223 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
224 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
211 return; 225 return;
212 226
213 if (m_TransferModule != null) 227 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index c20369c..145f3db 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -873,6 +873,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
873 } 873 }
874 #endregion Notes 874 #endregion Notes
875 875
876
876 #region User Preferences 877 #region User Preferences
877 /// <summary> 878 /// <summary>
878 /// Updates the user preferences. 879 /// Updates the user preferences.
@@ -1402,5 +1403,182 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1402 return null; 1403 return null;
1403 } 1404 }
1404 #endregion Util 1405 #endregion Util
1406
1407 #region Web Util
1408 /// <summary>
1409 /// Sends json-rpc request with a serializable type.
1410 /// </summary>
1411 /// <returns>
1412 /// OSD Map.
1413 /// </returns>
1414 /// <param name='parameters'>
1415 /// Serializable type .
1416 /// </param>
1417 /// <param name='method'>
1418 /// Json-rpc method to call.
1419 /// </param>
1420 /// <param name='uri'>
1421 /// URI of json-rpc service.
1422 /// </param>
1423 /// <param name='jsonId'>
1424 /// Id for our call.
1425 /// </param>
1426 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1427 {
1428 if (jsonId == null)
1429 throw new ArgumentNullException ("jsonId");
1430 if (uri == null)
1431 throw new ArgumentNullException ("uri");
1432 if (method == null)
1433 throw new ArgumentNullException ("method");
1434 if (parameters == null)
1435 throw new ArgumentNullException ("parameters");
1436
1437 // Prep our payload
1438 OSDMap json = new OSDMap();
1439
1440 json.Add("jsonrpc", OSD.FromString("2.0"));
1441 json.Add("id", OSD.FromString(jsonId));
1442 json.Add("method", OSD.FromString(method));
1443
1444 json.Add("params", OSD.SerializeMembers(parameters));
1445
1446 string jsonRequestData = OSDParser.SerializeJsonString(json);
1447 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1448
1449 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1450
1451 webRequest.ContentType = "application/json-rpc";
1452 webRequest.Method = "POST";
1453
1454 Stream dataStream = webRequest.GetRequestStream();
1455 dataStream.Write(content, 0, content.Length);
1456 dataStream.Close();
1457
1458 WebResponse webResponse = null;
1459 try
1460 {
1461 webResponse = webRequest.GetResponse();
1462 }
1463 catch (WebException e)
1464 {
1465 Console.WriteLine("Web Error" + e.Message);
1466 Console.WriteLine ("Please check input");
1467 return false;
1468 }
1469
1470 OSDMap mret = new OSDMap();
1471
1472 using (Stream rstream = webResponse.GetResponseStream())
1473 {
1474 try
1475 {
1476 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1477 }
1478 catch (Exception e)
1479 {
1480 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1481 if (webResponse != null)
1482 webResponse.Close();
1483 return false;
1484 }
1485 }
1486
1487 if (webResponse != null)
1488 webResponse.Close();
1489
1490 if (mret.ContainsKey("error"))
1491 return false;
1492
1493 // get params...
1494 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1495 return true;
1496 }
1497
1498 /// <summary>
1499 /// Sends json-rpc request with OSD parameter.
1500 /// </summary>
1501 /// <returns>
1502 /// The rpc request.
1503 /// </returns>
1504 /// <param name='data'>
1505 /// data - incoming as parameters, outgong as result/error
1506 /// </param>
1507 /// <param name='method'>
1508 /// Json-rpc method to call.
1509 /// </param>
1510 /// <param name='uri'>
1511 /// URI of json-rpc service.
1512 /// </param>
1513 /// <param name='jsonId'>
1514 /// If set to <c>true</c> json identifier.
1515 /// </param>
1516 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1517 {
1518 OSDMap map = new OSDMap();
1519
1520 map["jsonrpc"] = "2.0";
1521 if(string.IsNullOrEmpty(jsonId))
1522 map["id"] = UUID.Random().ToString();
1523 else
1524 map["id"] = jsonId;
1525
1526 map["method"] = method;
1527 map["params"] = data;
1528
1529 string jsonRequestData = OSDParser.SerializeJsonString(map);
1530 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1531
1532 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1533 webRequest.ContentType = "application/json-rpc";
1534 webRequest.Method = "POST";
1535
1536 Stream dataStream = webRequest.GetRequestStream();
1537 dataStream.Write(content, 0, content.Length);
1538 dataStream.Close();
1539
1540 WebResponse webResponse = null;
1541 try
1542 {
1543 webResponse = webRequest.GetResponse();
1544 }
1545 catch (WebException e)
1546 {
1547 Console.WriteLine("Web Error" + e.Message);
1548 Console.WriteLine ("Please check input");
1549 return false;
1550 }
1551
1552 OSDMap response = new OSDMap();
1553
1554 using (Stream rstream = webResponse.GetResponseStream())
1555 {
1556 try
1557 {
1558 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1559 }
1560 catch (Exception e)
1561 {
1562 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1563 if (webResponse != null)
1564 webResponse.Close();
1565 return false;
1566 }
1567 }
1568
1569 if (webResponse != null)
1570 webResponse.Close();
1571
1572 if(response.ContainsKey("error"))
1573 {
1574 data = response["error"];
1575 return false;
1576 }
1577
1578 data = response;
1579
1580 return true;
1581 }
1582 #endregion Web Util
1405 } 1583 }
1406} 1584}