aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorSean McNamara2011-04-23 18:33:08 -0400
committerSean McNamara2011-04-23 18:33:08 -0400
commitd287e0ac683acb0cab51bf0dbbc9d1fd08bd6bc9 (patch)
tree30a24bf66050c66ebe74b68745c4f1764fe09181 /OpenSim/Region
parentAutoBackup: Removed unneeded imports. (diff)
parentAdded MaxAgents configuration option to RegionConfig.ini allowing region host... (diff)
downloadopensim-SC-d287e0ac683acb0cab51bf0dbbc9d1fd08bd6bc9.zip
opensim-SC-d287e0ac683acb0cab51bf0dbbc9d1fd08bd6bc9.tar.gz
opensim-SC-d287e0ac683acb0cab51bf0dbbc9d1fd08bd6bc9.tar.bz2
opensim-SC-d287e0ac683acb0cab51bf0dbbc9d1fd08bd6bc9.tar.xz
Merge git://opensimulator.org/git/opensim
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs18
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs566
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs110
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs245
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs297
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs54
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs57
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs79
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs674
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs174
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs42
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs18
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs46
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs54
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs18
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs154
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs252
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs31
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs18
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs126
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs12
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs3
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs3
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMap.cs13
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs14
67 files changed, 2410 insertions, 1187 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index ec1fb04..39004d4 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -341,10 +341,15 @@ namespace OpenSim
341 341
342 m_console.Commands.AddCommand("region", false, "config get", 342 m_console.Commands.AddCommand("region", false, "config get",
343 "config get [<section>] [<key>]", 343 "config get [<section>] [<key>]",
344 "Show a config option", 344 "Synonym for config show",
345 HandleConfig);
346
347 m_console.Commands.AddCommand("region", false, "config show",
348 "config show [<section>] [<key>]",
349 "Show config information",
345 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine 350 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
346 + "If a section is given but not a field, then all fields in that section are printed.", 351 + "If a section is given but not a field, then all fields in that section are printed.",
347 HandleConfig); 352 HandleConfig);
348 353
349 m_console.Commands.AddCommand("region", false, "config save", 354 m_console.Commands.AddCommand("region", false, "config save",
350 "config save <path>", 355 "config save <path>",
@@ -593,7 +598,9 @@ namespace OpenSim
593 598
594 if (cmdparams.Length > 0) 599 if (cmdparams.Length > 0)
595 { 600 {
596 switch (cmdparams[0].ToLower()) 601 string firstParam = cmdparams[0].ToLower();
602
603 switch (firstParam)
597 { 604 {
598 case "set": 605 case "set":
599 if (cmdparams.Length < 4) 606 if (cmdparams.Length < 4)
@@ -618,6 +625,7 @@ namespace OpenSim
618 break; 625 break;
619 626
620 case "get": 627 case "get":
628 case "show":
621 if (cmdparams.Length == 1) 629 if (cmdparams.Length == 1)
622 { 630 {
623 foreach (IConfig config in m_config.Source.Configs) 631 foreach (IConfig config in m_config.Source.Configs)
@@ -654,8 +662,8 @@ namespace OpenSim
654 } 662 }
655 else 663 else
656 { 664 {
657 Notice("Syntax: config get [<section>] [<key>]"); 665 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
658 Notice("Example: config get ScriptEngine.DotNetEngine NumberOfScriptThreads"); 666 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
659 } 667 }
660 668
661 break; 669 break;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 34d72ac..1f7e66d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -49,6 +49,8 @@ using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using Nini.Config; 50using Nini.Config;
51 51
52using System.IO;
53
52namespace OpenSim.Region.ClientStack.LindenUDP 54namespace OpenSim.Region.ClientStack.LindenUDP
53{ 55{
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 56 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
@@ -313,6 +315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
313 315
314 private int m_cachedTextureSerial; 316 private int m_cachedTextureSerial;
315 private PriorityQueue m_entityUpdates; 317 private PriorityQueue m_entityUpdates;
318 private PriorityQueue m_entityProps;
316 private Prioritizer m_prioritizer; 319 private Prioritizer m_prioritizer;
317 private bool m_disableFacelights = false; 320 private bool m_disableFacelights = false;
318 321
@@ -360,9 +363,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
360 protected IAssetService m_assetService; 363 protected IAssetService m_assetService;
361 private const bool m_checkPackets = true; 364 private const bool m_checkPackets = true;
362 365
363 private Timer m_propertiesPacketTimer;
364 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
365
366 #endregion Class Members 366 #endregion Class Members
367 367
368 #region Properties 368 #region Properties
@@ -438,6 +438,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 m_scene = scene; 438 m_scene = scene;
439 439
440 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 440 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
441 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
441 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 442 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
442 m_killRecord = new HashSet<uint>(); 443 m_killRecord = new HashSet<uint>();
443// m_attachmentsSent = new HashSet<uint>(); 444// m_attachmentsSent = new HashSet<uint>();
@@ -461,9 +462,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 462 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
462 m_udpClient.OnPacketStats += PopulateStats; 463 m_udpClient.OnPacketStats += PopulateStats;
463 464
464 m_propertiesPacketTimer = new Timer(100);
465 m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket;
466
467 m_prioritizer = new Prioritizer(m_scene); 465 m_prioritizer = new Prioritizer(m_scene);
468 466
469 RegisterLocalPacketHandlers(); 467 RegisterLocalPacketHandlers();
@@ -1537,7 +1535,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1537 } 1535 }
1538 else 1536 else
1539 { 1537 {
1540 OutPacket(kill, ThrottleOutPacketType.State); 1538 // OutPacket(kill, ThrottleOutPacketType.State);
1539 OutPacket(kill, ThrottleOutPacketType.Task);
1541 } 1540 }
1542 } 1541 }
1543 1542
@@ -2367,7 +2366,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2367 2366
2368 packet.Effect = effectBlocks; 2367 packet.Effect = effectBlocks;
2369 2368
2370 OutPacket(packet, ThrottleOutPacketType.State); 2369 // OutPacket(packet, ThrottleOutPacketType.State);
2370 OutPacket(packet, ThrottleOutPacketType.Task);
2371 } 2371 }
2372 2372
2373 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, 2373 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
@@ -3547,16 +3547,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3547 3547
3548 #region Primitive Packet/Data Sending Methods 3548 #region Primitive Packet/Data Sending Methods
3549 3549
3550
3550 /// <summary> 3551 /// <summary>
3551 /// Generate one of the object update packets based on PrimUpdateFlags 3552 /// Generate one of the object update packets based on PrimUpdateFlags
3552 /// and broadcast the packet to clients 3553 /// and broadcast the packet to clients
3553 /// </summary> 3554 /// </summary>
3554 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3555 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3555 { 3556 {
3556 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3557 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3558 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3557 3559
3558 lock (m_entityUpdates.SyncRoot) 3560 lock (m_entityUpdates.SyncRoot)
3559 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation), entity.LocalId); 3561 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3560 } 3562 }
3561 3563
3562 private void ProcessEntityUpdates(int maxUpdates) 3564 private void ProcessEntityUpdates(int maxUpdates)
@@ -3566,7 +3568,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3566 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3568 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3567 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3569 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3568 3570
3569 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3571 // Check to see if this is a flush
3572 if (maxUpdates <= 0)
3573 {
3574 maxUpdates = Int32.MaxValue;
3575 }
3576
3570 int updatesThisCall = 0; 3577 int updatesThisCall = 0;
3571 3578
3572 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3579 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
@@ -3574,12 +3581,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3574 lock (m_killRecord) 3581 lock (m_killRecord)
3575 { 3582 {
3576 float avgTimeDilation = 1.0f; 3583 float avgTimeDilation = 1.0f;
3577 EntityUpdate update; 3584 IEntityUpdate iupdate;
3585 Int32 timeinqueue; // this is just debugging code & can be dropped later
3586
3578 while (updatesThisCall < maxUpdates) 3587 while (updatesThisCall < maxUpdates)
3579 { 3588 {
3580 lock (m_entityUpdates.SyncRoot) 3589 lock (m_entityUpdates.SyncRoot)
3581 if (!m_entityUpdates.TryDequeue(out update)) 3590 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3582 break; 3591 break;
3592
3593 EntityUpdate update = (EntityUpdate)iupdate;
3594
3583 avgTimeDilation += update.TimeDilation; 3595 avgTimeDilation += update.TimeDilation;
3584 avgTimeDilation *= 0.5f; 3596 avgTimeDilation *= 0.5f;
3585 3597
@@ -3619,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3619 3631
3620 #region UpdateFlags to packet type conversion 3632 #region UpdateFlags to packet type conversion
3621 3633
3622 PrimUpdateFlags updateFlags = update.Flags; 3634 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3623 3635
3624 bool canUseCompressed = true; 3636 bool canUseCompressed = true;
3625 bool canUseImproved = true; 3637 bool canUseImproved = true;
@@ -3679,36 +3691,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3679 } 3691 }
3680 else 3692 else
3681 { 3693 {
3682 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) 3694 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3683 // {
3684 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3685 // string text = sop.Text;
3686 // if (text.IndexOf("\n") >= 0)
3687 // text = text.Remove(text.IndexOf("\n"));
3688 //
3689 // if (m_attachmentsSent.Contains(sop.ParentID))
3690 // {
3691 //// m_log.DebugFormat(
3692 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3693 //// sop.LocalId, text);
3694 //
3695 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3696 //
3697 // m_attachmentsSent.Add(sop.LocalId);
3698 // }
3699 // else
3700 // {
3701 // m_log.DebugFormat(
3702 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3703 // sop.LocalId, text, sop.ParentID);
3704 //
3705 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3706 // }
3707 // }
3708 // else
3709 // {
3710 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3711 // }
3712 } 3695 }
3713 } 3696 }
3714 else if (!canUseImproved) 3697 else if (!canUseImproved)
@@ -3727,6 +3710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3727 3710
3728 #endregion Block Construction 3711 #endregion Block Construction
3729 } 3712 }
3713
3730 3714
3731 #region Packet Sending 3715 #region Packet Sending
3732 3716
@@ -3802,26 +3786,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3802 3786
3803 public void ReprioritizeUpdates() 3787 public void ReprioritizeUpdates()
3804 { 3788 {
3805 //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
3806
3807 lock (m_entityUpdates.SyncRoot) 3789 lock (m_entityUpdates.SyncRoot)
3808 m_entityUpdates.Reprioritize(UpdatePriorityHandler); 3790 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3809 } 3791 }
3810 3792
3811 private bool UpdatePriorityHandler(ref double priority, uint localID) 3793 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3812 { 3794 {
3813 EntityBase entity; 3795 if (entity != null)
3814 if (m_scene.Entities.TryGetValue(localID, out entity))
3815 { 3796 {
3816 priority = m_prioritizer.GetUpdatePriority(this, entity); 3797 priority = m_prioritizer.GetUpdatePriority(this, entity);
3798 return true;
3817 } 3799 }
3818 3800
3819 return priority != double.NaN; 3801 return false;
3820 } 3802 }
3821 3803
3822 public void FlushPrimUpdates() 3804 public void FlushPrimUpdates()
3823 { 3805 {
3824 m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); 3806 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3825 3807
3826 while (m_entityUpdates.Count > 0) 3808 while (m_entityUpdates.Count > 0)
3827 ProcessEntityUpdates(-1); 3809 ProcessEntityUpdates(-1);
@@ -3829,12 +3811,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3829 3811
3830 #endregion Primitive Packet/Data Sending Methods 3812 #endregion Primitive Packet/Data Sending Methods
3831 3813
3814 // These are used to implement an adaptive backoff in the number
3815 // of updates converted to packets. Since we don't want packets
3816 // to sit in the queue with old data, only convert enough updates
3817 // to packets that can be sent in 200ms.
3818 private Int32 m_LastQueueFill = 0;
3819 private Int32 m_maxUpdates = 0;
3820
3832 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 3821 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
3833 { 3822 {
3834 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 3823 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3835 { 3824 {
3825 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3826 {
3827 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
3828 }
3829 else
3830 {
3831 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3832 m_maxUpdates += 5;
3833 else
3834 m_maxUpdates = m_maxUpdates >> 1;
3835 }
3836 m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500);
3837 m_LastQueueFill = Util.EnvironmentTickCount();
3838
3836 if (m_entityUpdates.Count > 0) 3839 if (m_entityUpdates.Count > 0)
3837 ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback); 3840 ProcessEntityUpdates(m_maxUpdates);
3841
3842 if (m_entityProps.Count > 0)
3843 ProcessEntityPropertyRequests(m_maxUpdates);
3838 } 3844 }
3839 3845
3840 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) 3846 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -3948,132 +3954,206 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3948 OutPacket(pack, ThrottleOutPacketType.Task); 3954 OutPacket(pack, ThrottleOutPacketType.Task);
3949 } 3955 }
3950 3956
3951 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, 3957 private class ObjectPropertyUpdate : IEntityUpdate
3952 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
3953 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category,
3954 UUID LastOwnerID, string ObjectName, string Description)
3955 { 3958 {
3956 ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); 3959 internal bool SendFamilyProps;
3957 // TODO: don't create new blocks if recycling an old packet 3960 internal bool SendObjectProps;
3958 3961
3959 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); 3962 public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj)
3960 objPropDB.RequestFlags = RequestFlags; 3963 : base(entity,flags)
3961 objPropDB.ObjectID = ObjectUUID; 3964 {
3962 if (OwnerID == GroupID) 3965 SendFamilyProps = sendfam;
3963 objPropDB.OwnerID = UUID.Zero; 3966 SendObjectProps = sendobj;
3964 else 3967 }
3965 objPropDB.OwnerID = OwnerID; 3968 public void Update(ObjectPropertyUpdate update)
3966 objPropDB.GroupID = GroupID; 3969 {
3967 objPropDB.BaseMask = BaseMask; 3970 SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
3968 objPropDB.OwnerMask = OwnerMask; 3971 SendObjectProps = SendObjectProps || update.SendObjectProps;
3969 objPropDB.GroupMask = GroupMask; 3972 Flags |= update.Flags;
3970 objPropDB.EveryoneMask = EveryoneMask; 3973 }
3971 objPropDB.NextOwnerMask = NextOwnerMask; 3974 }
3975
3976 public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
3977 {
3978 uint priority = 0; // time based ordering only
3979 lock (m_entityProps.SyncRoot)
3980 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
3981 }
3972 3982
3973 // TODO: More properties are needed in SceneObjectPart! 3983 public void SendObjectPropertiesReply(ISceneEntity entity)
3974 objPropDB.OwnershipCost = OwnershipCost;
3975 objPropDB.SaleType = SaleType;
3976 objPropDB.SalePrice = SalePrice;
3977 objPropDB.Category = Category;
3978 objPropDB.LastOwnerID = LastOwnerID;
3979 objPropDB.Name = Util.StringToBytes256(ObjectName);
3980 objPropDB.Description = Util.StringToBytes256(Description);
3981 objPropFamilyPack.ObjectData = objPropDB;
3982 objPropFamilyPack.Header.Zerocoded = true;
3983 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
3984 }
3985
3986 public void SendObjectPropertiesReply(
3987 UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID,
3988 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
3989 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
3990 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
3991 uint BaseMask, byte saleType, int salePrice)
3992 { 3984 {
3993 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 3985 uint priority = 0; // time based ordering only
3994 // TODO: don't create new blocks if recycling an old packet 3986 lock (m_entityProps.SyncRoot)
3987 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
3988 }
3995 3989
3996 ObjectPropertiesPacket.ObjectDataBlock block = 3990 private void ProcessEntityPropertyRequests(int maxUpdates)
3997 new ObjectPropertiesPacket.ObjectDataBlock(); 3991 {
3992 OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
3993 new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
3998 3994
3999 block.ItemID = ItemID; 3995 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4000 block.CreationDate = CreationDate; 3996 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4001 block.CreatorID = CreatorUUID;
4002 block.FolderID = FolderUUID;
4003 block.FromTaskID = FromTaskUUID;
4004 block.GroupID = GroupUUID;
4005 block.InventorySerial = InventorySerial;
4006 3997
4007 block.LastOwnerID = LastOwnerUUID; 3998 IEntityUpdate iupdate;
4008 // proper.ObjectData[0].LastOwnerID = UUID.Zero; 3999 Int32 timeinqueue; // this is just debugging code & can be dropped later
4009 4000
4010 block.ObjectID = ObjectUUID; 4001 int updatesThisCall = 0;
4011 if (OwnerUUID == GroupUUID) 4002 while (updatesThisCall < m_maxUpdates)
4012 block.OwnerID = UUID.Zero;
4013 else
4014 block.OwnerID = OwnerUUID;
4015 block.TouchName = Util.StringToBytes256(TouchTitle);
4016 block.TextureID = TextureID;
4017 block.SitName = Util.StringToBytes256(SitTitle);
4018 block.Name = Util.StringToBytes256(ItemName);
4019 block.Description = Util.StringToBytes256(ItemDescription);
4020 block.OwnerMask = OwnerMask;
4021 block.NextOwnerMask = NextOwnerMask;
4022 block.GroupMask = GroupMask;
4023 block.EveryoneMask = EveryoneMask;
4024 block.BaseMask = BaseMask;
4025 // proper.ObjectData[0].AggregatePerms = 53;
4026 // proper.ObjectData[0].AggregatePermTextures = 0;
4027 // proper.ObjectData[0].AggregatePermTexturesOwner = 0;
4028 block.SaleType = saleType;
4029 block.SalePrice = salePrice;
4030
4031 lock (m_propertiesPacketTimer)
4032 { 4003 {
4033 m_propertiesBlocks.Add(block); 4004 lock (m_entityProps.SyncRoot)
4005 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4006 break;
4034 4007
4035 int length = 0; 4008 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4036 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4009 if (update.SendFamilyProps)
4037 { 4010 {
4038 length += b.Length; 4011 if (update.Entity is SceneObjectPart)
4012 {
4013 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4014 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4015 objectFamilyBlocks.Value.Add(objPropDB);
4016 }
4039 } 4017 }
4040 if (length > 1100) // FIXME: use real MTU 4018
4019 if (update.SendObjectProps)
4041 { 4020 {
4042 ProcessObjectPropertiesPacket(null, null); 4021 if (update.Entity is SceneObjectPart)
4043 m_propertiesPacketTimer.Stop(); 4022 {
4044 return; 4023 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4024 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4025 objectPropertiesBlocks.Value.Add(objPropDB);
4026 }
4045 } 4027 }
4046 4028
4047 m_propertiesPacketTimer.Stop(); 4029 updatesThisCall++;
4048 m_propertiesPacketTimer.Start();
4049 } 4030 }
4031
4050 4032
4051 //proper.Header.Zerocoded = true; 4033 Int32 ppcnt = 0;
4052 //OutPacket(proper, ThrottleOutPacketType.Task); 4034 Int32 pbcnt = 0;
4053 } 4035
4036 if (objectPropertiesBlocks.IsValueCreated)
4037 {
4038 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4054 4039
4055 private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e) 4040 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4056 { 4041 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
4057 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4042 for (int i = 0; i < blocks.Count; i++)
4043 packet.ObjectData[i] = blocks[i];
4058 4044
4059 lock (m_propertiesPacketTimer) 4045 packet.Header.Zerocoded = true;
4060 { 4046 OutPacket(packet, ThrottleOutPacketType.Task, true);
4061 m_propertiesPacketTimer.Stop();
4062 4047
4063 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4048 pbcnt += blocks.Count;
4049 ppcnt++;
4050 }
4051
4052 Int32 fpcnt = 0;
4053 Int32 fbcnt = 0;
4054
4055 if (objectFamilyBlocks.IsValueCreated)
4056 {
4057 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4064 4058
4065 int index = 0; 4059 // ObjectPropertiesFamilyPacket objPropFamilyPack =
4060 // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4061 //
4062 // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
4063 // for (int i = 0; i < blocks.Count; i++)
4064 // objPropFamilyPack.ObjectData[i] = blocks[i];
4065 //
4066 // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
4066 4067
4067 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4068 // one packet per object block... uggh...
4069 for (int i = 0; i < blocks.Count; i++)
4068 { 4070 {
4069 proper.ObjectData[index++] = b; 4071 ObjectPropertiesFamilyPacket packet =
4070 } 4072 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4073
4074 packet.ObjectData = blocks[i];
4075 packet.Header.Zerocoded = true;
4076 OutPacket(packet, ThrottleOutPacketType.Task);
4071 4077
4072 m_propertiesBlocks.Clear(); 4078 fpcnt++;
4079 fbcnt++;
4080 }
4081
4073 } 4082 }
4083
4084 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
4085 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt);
4086 }
4087
4088 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags)
4089 {
4090 ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4074 4091
4075 proper.Header.Zerocoded = true; 4092 block.RequestFlags = requestFlags;
4076 OutPacket(proper, ThrottleOutPacketType.Task); 4093 block.ObjectID = sop.UUID;
4094 if (sop.OwnerID == sop.GroupID)
4095 block.OwnerID = UUID.Zero;
4096 else
4097 block.OwnerID = sop.OwnerID;
4098 block.GroupID = sop.GroupID;
4099 block.BaseMask = sop.BaseMask;
4100 block.OwnerMask = sop.OwnerMask;
4101 block.GroupMask = sop.GroupMask;
4102 block.EveryoneMask = sop.EveryoneMask;
4103 block.NextOwnerMask = sop.NextOwnerMask;
4104
4105 // TODO: More properties are needed in SceneObjectPart!
4106 block.OwnershipCost = sop.OwnershipCost;
4107 block.SaleType = sop.ObjectSaleType;
4108 block.SalePrice = sop.SalePrice;
4109 block.Category = sop.Category;
4110 block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right?
4111 block.Name = Util.StringToBytes256(sop.Name);
4112 block.Description = Util.StringToBytes256(sop.Description);
4113
4114 return block;
4115 }
4116
4117 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4118 {
4119 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4120 // TODO: don't create new blocks if recycling an old packet
4121
4122 ObjectPropertiesPacket.ObjectDataBlock block =
4123 new ObjectPropertiesPacket.ObjectDataBlock();
4124
4125 block.ObjectID = sop.UUID;
4126 block.Name = Util.StringToBytes256(sop.Name);
4127 block.Description = Util.StringToBytes256(sop.Description);
4128
4129 block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds
4130 block.CreatorID = sop.CreatorID;
4131 block.GroupID = sop.GroupID;
4132 block.LastOwnerID = sop.LastOwnerID;
4133 if (sop.OwnerID == sop.GroupID)
4134 block.OwnerID = UUID.Zero;
4135 else
4136 block.OwnerID = sop.OwnerID;
4137
4138 block.ItemID = sop.FromUserInventoryItemID;
4139 block.FolderID = UUID.Zero; // sop.FromFolderID ??
4140 block.FromTaskID = UUID.Zero; // ???
4141 block.InventorySerial = (short)sop.InventorySerial;
4142
4143 SceneObjectPart root = sop.ParentGroup.RootPart;
4144
4145 block.TouchName = Util.StringToBytes256(root.TouchName);
4146 block.TextureID = new byte[0]; // TextureID ???
4147 block.SitName = Util.StringToBytes256(root.SitName);
4148 block.OwnerMask = root.OwnerMask;
4149 block.NextOwnerMask = root.NextOwnerMask;
4150 block.GroupMask = root.GroupMask;
4151 block.EveryoneMask = root.EveryoneMask;
4152 block.BaseMask = root.BaseMask;
4153 block.SaleType = root.ObjectSaleType;
4154 block.SalePrice = root.SalePrice;
4155
4156 return block;
4077 } 4157 }
4078 4158
4079 #region Estate Data Sending Methods 4159 #region Estate Data Sending Methods
@@ -4217,6 +4297,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4217 4297
4218 public void SendEstateCovenantInformation(UUID covenant) 4298 public void SendEstateCovenantInformation(UUID covenant)
4219 { 4299 {
4300// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name);
4301
4220 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); 4302 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket();
4221 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); 4303 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4222 edata.CovenantID = covenant; 4304 edata.CovenantID = covenant;
@@ -4227,8 +4309,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4227 OutPacket(einfopack, ThrottleOutPacketType.Task); 4309 OutPacket(einfopack, ThrottleOutPacketType.Task);
4228 } 4310 }
4229 4311
4230 public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) 4312 public void SendDetailedEstateData(
4313 UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition,
4314 UUID covenant, string abuseEmail, UUID estateOwner)
4231 { 4315 {
4316// m_log.DebugFormat(
4317// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant);
4318
4232 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4319 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4233 packet.MethodData.Invoice = invoice; 4320 packet.MethodData.Invoice = invoice;
4234 packet.AgentData.TransactionID = UUID.Random(); 4321 packet.AgentData.TransactionID = UUID.Random();
@@ -4407,6 +4494,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4407 4494
4408 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 4495 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4409 { 4496 {
4497 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4498
4410 bool firstCall = true; 4499 bool firstCall = true;
4411 const int MAX_OBJECTS_PER_PACKET = 251; 4500 const int MAX_OBJECTS_PER_PACKET = 251;
4412 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); 4501 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
@@ -11298,7 +11387,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11298 if (logPacket) 11387 if (logPacket)
11299 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); 11388 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11300 } 11389 }
11301 11390
11302 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); 11391 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
11303 } 11392 }
11304 11393
@@ -11726,171 +11815,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11726 OutPacket(pack, ThrottleOutPacketType.Task); 11815 OutPacket(pack, ThrottleOutPacketType.Task);
11727 } 11816 }
11728 11817
11729 #region PriorityQueue
11730 public class PriorityQueue
11731 {
11732 internal delegate bool UpdatePriorityHandler(ref double priority, uint local_id);
11733
11734 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
11735 private Dictionary<uint, LookupItem> m_lookupTable;
11736 private Comparison<double> m_comparison;
11737 private object m_syncRoot = new object();
11738
11739 internal PriorityQueue() :
11740 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<double>.Default) { }
11741 internal PriorityQueue(int capacity) :
11742 this(capacity, Comparer<double>.Default) { }
11743 internal PriorityQueue(IComparer<double> comparer) :
11744 this(new Comparison<double>(comparer.Compare)) { }
11745 internal PriorityQueue(Comparison<double> comparison) :
11746 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
11747 internal PriorityQueue(int capacity, IComparer<double> comparer) :
11748 this(capacity, new Comparison<double>(comparer.Compare)) { }
11749 internal PriorityQueue(int capacity, Comparison<double> comparison)
11750 {
11751 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
11752
11753 for (int i = 0; i < m_heaps.Length; ++i)
11754 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
11755 this.m_comparison = comparison;
11756 }
11757
11758 public object SyncRoot { get { return this.m_syncRoot; } }
11759 internal int Count
11760 {
11761 get
11762 {
11763 int count = 0;
11764 for (int i = 0; i < m_heaps.Length; ++i)
11765 count = m_heaps[i].Count;
11766 return count;
11767 }
11768 }
11769
11770 public bool Enqueue(double priority, EntityUpdate value, uint local_id)
11771 {
11772 LookupItem item;
11773
11774 if (m_lookupTable.TryGetValue(local_id, out item))
11775 {
11776 // Combine flags
11777 value.Flags |= item.Heap[item.Handle].Value.Flags;
11778
11779 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
11780 return false;
11781 }
11782 else
11783 {
11784 item.Heap = m_heaps[0];
11785 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
11786 m_lookupTable.Add(local_id, item);
11787 return true;
11788 }
11789 }
11790
11791 internal EntityUpdate Peek()
11792 {
11793 for (int i = 0; i < m_heaps.Length; ++i)
11794 if (m_heaps[i].Count > 0)
11795 return m_heaps[i].Min().Value;
11796 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11797 }
11798
11799 internal bool TryDequeue(out EntityUpdate value)
11800 {
11801 for (int i = 0; i < m_heaps.Length; ++i)
11802 {
11803 if (m_heaps[i].Count > 0)
11804 {
11805 MinHeapItem item = m_heaps[i].RemoveMin();
11806 m_lookupTable.Remove(item.LocalID);
11807 value = item.Value;
11808 return true;
11809 }
11810 }
11811
11812 value = default(EntityUpdate);
11813 return false;
11814 }
11815
11816 internal void Reprioritize(UpdatePriorityHandler handler)
11817 {
11818 MinHeapItem item;
11819 double priority;
11820
11821 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
11822 {
11823 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
11824 {
11825 priority = item.Priority;
11826 if (handler(ref priority, item.LocalID))
11827 {
11828 if (lookup.Heap.ContainsHandle(lookup.Handle))
11829 lookup.Heap[lookup.Handle] =
11830 new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
11831 }
11832 else
11833 {
11834 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
11835 lookup.Heap.Remove(lookup.Handle);
11836 this.m_lookupTable.Remove(item.LocalID);
11837 }
11838 }
11839 }
11840 }
11841
11842 #region MinHeapItem
11843 private struct MinHeapItem : IComparable<MinHeapItem>
11844 {
11845 private double priority;
11846 private EntityUpdate value;
11847 private uint local_id;
11848 private Comparison<double> comparison;
11849
11850 internal MinHeapItem(double priority, EntityUpdate value, uint local_id) :
11851 this(priority, value, local_id, Comparer<double>.Default) { }
11852 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, IComparer<double> comparer) :
11853 this(priority, value, local_id, new Comparison<double>(comparer.Compare)) { }
11854 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, Comparison<double> comparison)
11855 {
11856 this.priority = priority;
11857 this.value = value;
11858 this.local_id = local_id;
11859 this.comparison = comparison;
11860 }
11861
11862 internal double Priority { get { return this.priority; } }
11863 internal EntityUpdate Value { get { return this.value; } }
11864 internal uint LocalID { get { return this.local_id; } }
11865
11866 public override string ToString()
11867 {
11868 StringBuilder sb = new StringBuilder();
11869 sb.Append("[");
11870 sb.Append(this.priority.ToString());
11871 sb.Append(",");
11872 if (this.value != null)
11873 sb.Append(this.value.ToString());
11874 sb.Append("]");
11875 return sb.ToString();
11876 }
11877
11878 public int CompareTo(MinHeapItem other)
11879 {
11880 return this.comparison(this.priority, other.priority);
11881 }
11882 }
11883 #endregion
11884
11885 #region LookupItem
11886 private struct LookupItem
11887 {
11888 internal MinHeap<MinHeapItem> Heap;
11889 internal IHandle Handle;
11890 }
11891 #endregion
11892 }
11893
11894 public struct PacketProcessor 11818 public struct PacketProcessor
11895 { 11819 {
11896 public PacketMethod method; 11820 public PacketMethod method;
@@ -11911,8 +11835,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11911 } 11835 }
11912 } 11836 }
11913 11837
11914 #endregion
11915
11916 public static OSD BuildEvent(string eventName, OSD eventBody) 11838 public static OSD BuildEvent(string eventName, OSD eventBody)
11917 { 11839 {
11918 OSDMap osdEvent = new OSDMap(2); 11840 OSDMap osdEvent = new OSDMap(2);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 65a8fe3..7be8a0a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,7 +135,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
135 private int m_nextOnQueueEmpty = 1; 135 private int m_nextOnQueueEmpty = 1;
136 136
137 /// <summary>Throttle bucket for this agent's connection</summary> 137 /// <summary>Throttle bucket for this agent's connection</summary>
138 private readonly TokenBucket m_throttle; 138 private readonly TokenBucket m_throttleClient;
139 /// <summary>Throttle bucket for this agent's connection</summary>
140 private readonly TokenBucket m_throttleCategory;
139 /// <summary>Throttle buckets for each packet category</summary> 141 /// <summary>Throttle buckets for each packet category</summary>
140 private readonly TokenBucket[] m_throttleCategories; 142 private readonly TokenBucket[] m_throttleCategories;
141 /// <summary>Outgoing queues for throttled packets</summary> 143 /// <summary>Outgoing queues for throttled packets</summary>
@@ -149,7 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 /// <summary>Caches packed throttle information</summary> 151 /// <summary>Caches packed throttle information</summary>
150 private byte[] m_packedThrottles; 152 private byte[] m_packedThrottles;
151 153
152 private int m_defaultRTO = 3000; 154 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
153 private int m_maxRTO = 60000; 155 private int m_maxRTO = 60000;
154 156
155 /// <summary> 157 /// <summary>
@@ -174,7 +176,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
174 m_maxRTO = maxRTO; 176 m_maxRTO = maxRTO;
175 177
176 // Create a token bucket throttle for this client that has the scene token bucket as a parent 178 // Create a token bucket throttle for this client that has the scene token bucket as a parent
177 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total); 179 m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit);
180 // Create a token bucket throttle for the total categary with the client bucket as a throttle
181 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
178 // Create an array of token buckets for this clients different throttle categories 182 // Create an array of token buckets for this clients different throttle categories
179 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 183 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
180 184
@@ -185,7 +189,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
185 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 189 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
186 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 190 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
187 // Initialize the token buckets that control the throttling for each category 191 // Initialize the token buckets that control the throttling for each category
188 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); 192 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
189 } 193 }
190 194
191 // Default the retransmission timeout to three seconds 195 // Default the retransmission timeout to three seconds
@@ -206,6 +210,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
206 m_packetOutboxes[i].Clear(); 210 m_packetOutboxes[i].Clear();
207 m_nextPackets[i] = null; 211 m_nextPackets[i] = null;
208 } 212 }
213
214 // pull the throttle out of the scene throttle
215 m_throttleClient.Parent.UnregisterRequest(m_throttleClient);
209 OnPacketStats = null; 216 OnPacketStats = null;
210 OnQueueEmpty = null; 217 OnQueueEmpty = null;
211 } 218 }
@@ -216,6 +223,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
216 /// <returns>Information about the client connection</returns> 223 /// <returns>Information about the client connection</returns>
217 public ClientInfo GetClientInfo() 224 public ClientInfo GetClientInfo()
218 { 225 {
226///<mic>
227 TokenBucket tb;
228
229 tb = m_throttleClient.Parent;
230 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
231
232 tb = m_throttleClient;
233 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
234
235 tb = m_throttleCategory;
236 m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
237
238 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
239 {
240 tb = m_throttleCategories[i];
241 m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
242 }
243
244///</mic>
245
219 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists 246 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
220 // of pending and needed ACKs for every client every time some method wants information about 247 // of pending and needed ACKs for every client every time some method wants information about
221 // this connection is a recipe for poor performance 248 // this connection is a recipe for poor performance
@@ -223,13 +250,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
223 info.pendingAcks = new Dictionary<uint, uint>(); 250 info.pendingAcks = new Dictionary<uint, uint>();
224 info.needAck = new Dictionary<uint, byte[]>(); 251 info.needAck = new Dictionary<uint, byte[]>();
225 252
226 info.resendThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 253 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
227 info.landThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 254 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
228 info.windThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 255 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
229 info.cloudThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 256 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
230 info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 257 // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
231 info.assetThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 258 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
232 info.textureThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 259 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
260 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
233 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 261 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
234 info.taskThrottle + info.assetThrottle + info.textureThrottle; 262 info.taskThrottle + info.assetThrottle + info.textureThrottle;
235 263
@@ -317,8 +345,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
317 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 345 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
318 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 346 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
319 // State is a subcategory of task that we allocate a percentage to 347 // State is a subcategory of task that we allocate a percentage to
320 int state = (int)((float)task * STATE_TASK_PERCENTAGE); 348 int state = 0;
321 task -= state; 349 // int state = (int)((float)task * STATE_TASK_PERCENTAGE);
350 // task -= state;
322 351
323 // Make sure none of the throttles are set below our packet MTU, 352 // Make sure none of the throttles are set below our packet MTU,
324 // otherwise a throttle could become permanently clogged 353 // otherwise a throttle could become permanently clogged
@@ -339,40 +368,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
339 // Update the token buckets with new throttle values 368 // Update the token buckets with new throttle values
340 TokenBucket bucket; 369 TokenBucket bucket;
341 370
342 bucket = m_throttle; 371 bucket = m_throttleCategory;
343 bucket.MaxBurst = total; 372 bucket.RequestedDripRate = total;
344 373
345 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; 374 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
346 bucket.DripRate = resend; 375 bucket.RequestedDripRate = resend;
347 bucket.MaxBurst = resend;
348 376
349 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; 377 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
350 bucket.DripRate = land; 378 bucket.RequestedDripRate = land;
351 bucket.MaxBurst = land;
352 379
353 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; 380 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
354 bucket.DripRate = wind; 381 bucket.RequestedDripRate = wind;
355 bucket.MaxBurst = wind;
356 382
357 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; 383 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
358 bucket.DripRate = cloud; 384 bucket.RequestedDripRate = cloud;
359 bucket.MaxBurst = cloud;
360 385
361 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; 386 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
362 bucket.DripRate = asset; 387 bucket.RequestedDripRate = asset;
363 bucket.MaxBurst = asset;
364 388
365 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; 389 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
366 bucket.DripRate = task + state; 390 bucket.RequestedDripRate = task;
367 bucket.MaxBurst = task + state;
368 391
369 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State]; 392 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
370 bucket.DripRate = state; 393 bucket.RequestedDripRate = state;
371 bucket.MaxBurst = state;
372 394
373 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; 395 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
374 bucket.DripRate = texture; 396 bucket.RequestedDripRate = texture;
375 bucket.MaxBurst = texture;
376 397
377 // Reset the packed throttles cached data 398 // Reset the packed throttles cached data
378 m_packedThrottles = null; 399 m_packedThrottles = null;
@@ -387,14 +408,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
387 data = new byte[7 * 4]; 408 data = new byte[7 * 4];
388 int i = 0; 409 int i = 0;
389 410
390 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; 411 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
391 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 412 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
392 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; 413 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
393 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; 414 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
394 Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + 415 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
395 m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; 416 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
396 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 417 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
397 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
398 418
399 m_packedThrottles = data; 419 m_packedThrottles = data;
400 } 420 }
@@ -420,6 +440,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
420 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 440 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
421 TokenBucket bucket = m_throttleCategories[category]; 441 TokenBucket bucket = m_throttleCategories[category];
422 442
443 // Don't send this packet if there is already a packet waiting in the queue
444 // even if we have the tokens to send it, tokens should go to the already
445 // queued packets
446 if (queue.Count > 0)
447 {
448 queue.Enqueue(packet);
449 return true;
450 }
451
452
423 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 453 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
424 { 454 {
425 // Enough tokens were removed from the bucket, the packet will not be queued 455 // Enough tokens were removed from the bucket, the packet will not be queued
@@ -557,7 +587,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
557 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); 587 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
558 588
559 // Clamp the retransmission timeout to manageable values 589 // Clamp the retransmission timeout to manageable values
560 rto = Utils.Clamp(RTO, m_defaultRTO, m_maxRTO); 590 rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
561 591
562 RTO = rto; 592 RTO = rto;
563 593
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 583214c..d08b25f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -228,7 +228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
228 } 228 }
229 #endregion BinaryStats 229 #endregion BinaryStats
230 230
231 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps); 231 m_throttle = new TokenBucket(null, sceneThrottleBps);
232 ThrottleRates = new ThrottleRates(configSource); 232 ThrottleRates = new ThrottleRates(configSource);
233 } 233 }
234 234
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
new file mode 100644
index 0000000..b62ec07
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
@@ -0,0 +1,245 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Client;
35using log4net;
36
37namespace OpenSim.Region.ClientStack.LindenUDP
38{
39 public class PriorityQueue
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
44
45 // Heap[0] for self updates
46 // Heap[1..12] for entity updates
47
48 internal const uint m_numberOfQueues = 12;
49
50 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
51 private Dictionary<uint, LookupItem> m_lookupTable;
52 private uint m_nextQueue = 0;
53 private UInt64 m_nextRequest = 0;
54
55 private object m_syncRoot = new object();
56 public object SyncRoot {
57 get { return this.m_syncRoot; }
58 }
59
60 internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
61
62 internal PriorityQueue(int capacity)
63 {
64 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
65
66 for (int i = 0; i < m_heaps.Length; ++i)
67 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
68 }
69
70 internal int Count
71 {
72 get
73 {
74 int count = 0;
75 for (int i = 0; i < m_heaps.Length; ++i)
76 count += m_heaps[i].Count;
77 return count;
78 }
79 }
80
81 public bool Enqueue(uint pqueue, IEntityUpdate value)
82 {
83 LookupItem lookup;
84
85 uint localid = value.Entity.LocalId;
86 UInt64 entry = m_nextRequest++;
87 if (m_lookupTable.TryGetValue(localid, out lookup))
88 {
89 entry = lookup.Heap[lookup.Handle].EntryOrder;
90 value.Update(lookup.Heap[lookup.Handle].Value);
91 lookup.Heap.Remove(lookup.Handle);
92 }
93
94 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
95 lookup.Heap = m_heaps[pqueue];
96 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
97 m_lookupTable[localid] = lookup;
98
99 return true;
100 }
101
102 internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
103 {
104 for (int i = 0; i < m_numberOfQueues; ++i)
105 {
106 // To get the fair queing, we cycle through each of the
107 // queues when finding an element to dequeue, this code
108 // assumes that the distribution of updates in the queues
109 // is polynomial, probably quadractic (eg distance of PI * R^2)
110 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
111 if (m_heaps[h].Count > 0)
112 {
113 m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
114
115 MinHeapItem item = m_heaps[h].RemoveMin();
116 m_lookupTable.Remove(item.Value.Entity.LocalId);
117 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
118 value = item.Value;
119
120 return true;
121 }
122 }
123
124 timeinqueue = 0;
125 value = default(IEntityUpdate);
126 return false;
127 }
128
129 internal void Reprioritize(UpdatePriorityHandler handler)
130 {
131 MinHeapItem item;
132 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
133 {
134 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
135 {
136 uint pqueue = item.PriorityQueue;
137 uint localid = item.Value.Entity.LocalId;
138
139 if (handler(ref pqueue, item.Value.Entity))
140 {
141 // unless the priority queue has changed, there is no need to modify
142 // the entry
143 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
144 if (pqueue != item.PriorityQueue)
145 {
146 lookup.Heap.Remove(lookup.Handle);
147
148 LookupItem litem = lookup;
149 litem.Heap = m_heaps[pqueue];
150 litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle);
151 m_lookupTable[localid] = litem;
152 }
153 }
154 else
155 {
156 // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID);
157 lookup.Heap.Remove(lookup.Handle);
158 this.m_lookupTable.Remove(localid);
159 }
160 }
161 }
162 }
163
164 public override string ToString()
165 {
166 string s = "";
167 for (int i = 0; i < m_numberOfQueues; i++)
168 {
169 if (s != "") s += ",";
170 s += m_heaps[i].Count.ToString();
171 }
172 return s;
173 }
174
175#region MinHeapItem
176 private struct MinHeapItem : IComparable<MinHeapItem>
177 {
178 private IEntityUpdate value;
179 internal IEntityUpdate Value {
180 get {
181 return this.value;
182 }
183 }
184
185 private uint pqueue;
186 internal uint PriorityQueue {
187 get {
188 return this.pqueue;
189 }
190 }
191
192 private Int32 entrytime;
193 internal Int32 EntryTime {
194 get {
195 return this.entrytime;
196 }
197 }
198
199 private UInt64 entryorder;
200 internal UInt64 EntryOrder
201 {
202 get {
203 return this.entryorder;
204 }
205 }
206
207 internal MinHeapItem(uint pqueue, MinHeapItem other)
208 {
209 this.entrytime = other.entrytime;
210 this.entryorder = other.entryorder;
211 this.value = other.value;
212 this.pqueue = pqueue;
213 }
214
215 internal MinHeapItem(uint pqueue, UInt64 entryorder, IEntityUpdate value)
216 {
217 this.entrytime = Util.EnvironmentTickCount();
218 this.entryorder = entryorder;
219 this.value = value;
220 this.pqueue = pqueue;
221 }
222
223 public override string ToString()
224 {
225 return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId);
226 }
227
228 public int CompareTo(MinHeapItem other)
229 {
230 // I'm assuming that the root part of an SOG is added to the update queue
231 // before the component parts
232 return Comparer<UInt64>.Default.Compare(this.EntryOrder, other.EntryOrder);
233 }
234 }
235#endregion
236
237#region LookupItem
238 private struct LookupItem
239 {
240 internal MinHeap<MinHeapItem> Heap;
241 internal IHandle Handle;
242 }
243#endregion
244 }
245}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 0a8331f..07b0a1d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -26,6 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
29 33
30namespace OpenSim.Region.ClientStack.LindenUDP 34namespace OpenSim.Region.ClientStack.LindenUDP
31{ 35{
@@ -35,89 +39,126 @@ namespace OpenSim.Region.ClientStack.LindenUDP
35 /// </summary> 39 /// </summary>
36 public class TokenBucket 40 public class TokenBucket
37 { 41 {
38 /// <summary>Parent bucket to this bucket, or null if this is a root 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 /// bucket</summary> 43 private static Int32 m_counter = 0;
40 TokenBucket parent; 44
41 /// <summary>Size of the bucket in bytes. If zero, the bucket has 45 private Int32 m_identifier;
42 /// infinite capacity</summary> 46
43 int maxBurst; 47 /// <summary>
44 /// <summary>Rate that the bucket fills, in bytes per millisecond. If 48 /// Number of ticks (ms) per quantum, drip rate and max burst
45 /// zero, the bucket always remains full</summary> 49 /// are defined over this interval.
46 int tokensPerMS; 50 /// </summary>
47 /// <summary>Number of tokens currently in the bucket</summary> 51 private const Int32 m_ticksPerQuantum = 1000;
48 int content; 52
53 /// <summary>
54 /// This is the number of quantums worth of packets that can
55 /// be accommodated during a burst
56 /// </summary>
57 private const Double m_quantumsPerBurst = 1.5;
58
59 /// <summary>
60 /// </summary>
61 private const Int32 m_minimumDripRate = 1400;
62
49 /// <summary>Time of the last drip, in system ticks</summary> 63 /// <summary>Time of the last drip, in system ticks</summary>
50 int lastDrip; 64 private Int32 m_lastDrip;
51 65
52 #region Properties 66 /// <summary>
67 /// The number of bytes that can be sent at this moment. This is the
68 /// current number of tokens in the bucket
69 /// </summary>
70 private Int64 m_tokenCount;
71
72 /// <summary>
73 /// Map of children buckets and their requested maximum burst rate
74 /// </summary>
75 private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
76
77#region Properties
53 78
54 /// <summary> 79 /// <summary>
55 /// The parent bucket of this bucket, or null if this bucket has no 80 /// The parent bucket of this bucket, or null if this bucket has no
56 /// parent. The parent bucket will limit the aggregate bandwidth of all 81 /// parent. The parent bucket will limit the aggregate bandwidth of all
57 /// of its children buckets 82 /// of its children buckets
58 /// </summary> 83 /// </summary>
84 private TokenBucket m_parent;
59 public TokenBucket Parent 85 public TokenBucket Parent
60 { 86 {
61 get { return parent; } 87 get { return m_parent; }
88 set { m_parent = value; }
62 } 89 }
63 90
64 /// <summary> 91 /// <summary>
65 /// Maximum burst rate in bytes per second. This is the maximum number 92 /// Maximum burst rate in bytes per second. This is the maximum number
66 /// of tokens that can accumulate in the bucket at any one time 93 /// of tokens that can accumulate in the bucket at any one time. This
94 /// also sets the total request for leaf nodes
67 /// </summary> 95 /// </summary>
68 public int MaxBurst 96 private Int64 m_burstRate;
97 public Int64 RequestedBurstRate
69 { 98 {
70 get { return maxBurst; } 99 get { return m_burstRate; }
71 set { maxBurst = (value >= 0 ? value : 0); } 100 set { m_burstRate = (value < 0 ? 0 : value); }
72 } 101 }
73 102
103 public Int64 BurstRate
104 {
105 get {
106 double rate = RequestedBurstRate * BurstRateModifier();
107 if (rate < m_minimumDripRate * m_quantumsPerBurst)
108 rate = m_minimumDripRate * m_quantumsPerBurst;
109
110 return (Int64) rate;
111 }
112 }
113
74 /// <summary> 114 /// <summary>
75 /// The speed limit of this bucket in bytes per second. This is the 115 /// The speed limit of this bucket in bytes per second. This is the
76 /// number of tokens that are added to the bucket per second 116 /// number of tokens that are added to the bucket per quantum
77 /// </summary> 117 /// </summary>
78 /// <remarks>Tokens are added to the bucket any time 118 /// <remarks>Tokens are added to the bucket any time
79 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 119 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
80 /// the system tick interval (typically around 15-22ms)</remarks> 120 /// the system tick interval (typically around 15-22ms)</remarks>
81 public int DripRate 121 private Int64 m_dripRate;
122 public Int64 RequestedDripRate
82 { 123 {
83 get { return tokensPerMS * 1000; } 124 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
84 set 125 set {
85 { 126 m_dripRate = (value < 0 ? 0 : value);
86 if (value == 0) 127 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
87 tokensPerMS = 0; 128 m_totalDripRequest = m_dripRate;
88 else 129 if (m_parent != null)
89 { 130 m_parent.RegisterRequest(this,m_dripRate);
90 int bpms = (int)((float)value / 1000.0f);
91
92 if (bpms <= 0)
93 tokensPerMS = 1; // 1 byte/ms is the minimum granularity
94 else
95 tokensPerMS = bpms;
96 }
97 } 131 }
98 } 132 }
99 133
100 /// <summary> 134 public Int64 DripRate
101 /// The speed limit of this bucket in bytes per millisecond
102 /// </summary>
103 public int DripPerMS
104 { 135 {
105 get { return tokensPerMS; } 136 get {
137 if (m_parent == null)
138 return Math.Min(RequestedDripRate,TotalDripRequest);
139
140 double rate = (double)RequestedDripRate * m_parent.DripRateModifier();
141 if (rate < m_minimumDripRate)
142 rate = m_minimumDripRate;
143
144 return (Int64)rate;
145 }
106 } 146 }
107 147
108 /// <summary> 148 /// <summary>
109 /// The number of bytes that can be sent at this moment. This is the 149 /// The current total of the requested maximum burst rates of
110 /// current number of tokens in the bucket 150 /// this bucket's children buckets.
111 /// <remarks>If this bucket has a parent bucket that does not have
112 /// enough tokens for a request, <seealso cref="RemoveTokens"/> will
113 /// return false regardless of the content of this bucket</remarks>
114 /// </summary> 151 /// </summary>
115 public int Content 152 private Int64 m_totalDripRequest;
116 { 153 public Int64 TotalDripRequest
117 get { return content; } 154 {
118 } 155 get { return m_totalDripRequest; }
156 set { m_totalDripRequest = value; }
157 }
158
159#endregion Properties
119 160
120 #endregion Properties 161#region Constructor
121 162
122 /// <summary> 163 /// <summary>
123 /// Default constructor 164 /// Default constructor
@@ -128,56 +169,114 @@ namespace OpenSim.Region.ClientStack.LindenUDP
128 /// zero if this bucket has no maximum capacity</param> 169 /// zero if this bucket has no maximum capacity</param>
129 /// <param name="dripRate">Rate that the bucket fills, in bytes per 170 /// <param name="dripRate">Rate that the bucket fills, in bytes per
130 /// second. If zero, the bucket always remains full</param> 171 /// second. If zero, the bucket always remains full</param>
131 public TokenBucket(TokenBucket parent, int maxBurst, int dripRate) 172 public TokenBucket(TokenBucket parent, Int64 dripRate)
132 { 173 {
133 this.parent = parent; 174 m_identifier = m_counter++;
134 MaxBurst = maxBurst; 175
135 DripRate = dripRate; 176 Parent = parent;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 177 RequestedDripRate = dripRate;
178 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
179 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
180 m_lastDrip = Environment.TickCount & Int32.MaxValue;
137 } 181 }
138 182
183#endregion Constructor
184
139 /// <summary> 185 /// <summary>
140 /// Remove a given number of tokens from the bucket 186 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
187 /// no modification if the requested bandwidth is less than the
188 /// max burst bandwidth all the way to the root of the throttle
189 /// hierarchy. However, if any of the parents is over-booked, then
190 /// the modifier will be less than 1.
141 /// </summary> 191 /// </summary>
142 /// <param name="amount">Number of tokens to remove from the bucket</param> 192 private double DripRateModifier()
143 /// <returns>True if the requested number of tokens were removed from
144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount)
146 { 193 {
147 bool dummy; 194 Int64 driprate = DripRate;
148 return RemoveTokens(amount, out dummy); 195 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
149 } 196 }
150 197
151 /// <summary> 198 /// <summary>
199 /// </summary>
200 private double BurstRateModifier()
201 {
202 // for now... burst rate is always m_quantumsPerBurst (constant)
203 // larger than drip rate so the ratio of burst requests is the
204 // same as the drip ratio
205 return DripRateModifier();
206 }
207
208 /// <summary>
209 /// Register drip rate requested by a child of this throttle. Pass the
210 /// changes up the hierarchy.
211 /// </summary>
212 public void RegisterRequest(TokenBucket child, Int64 request)
213 {
214 m_children[child] = request;
215 // m_totalDripRequest = m_children.Values.Sum();
216
217 m_totalDripRequest = 0;
218 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
219 m_totalDripRequest += cref.Value;
220
221 // Pass the new values up to the parent
222 if (m_parent != null)
223 m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest));
224 }
225
226 /// <summary>
227 /// Remove the rate requested by a child of this throttle. Pass the
228 /// changes up the hierarchy.
229 /// </summary>
230 public void UnregisterRequest(TokenBucket child)
231 {
232 m_children.Remove(child);
233 // m_totalDripRequest = m_children.Values.Sum();
234
235 m_totalDripRequest = 0;
236 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children)
237 m_totalDripRequest += cref.Value;
238
239 // Pass the new values up to the parent
240 if (m_parent != null)
241 m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest));
242 }
243
244 /// <summary>
152 /// Remove a given number of tokens from the bucket 245 /// Remove a given number of tokens from the bucket
153 /// </summary> 246 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param> 247 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from 248 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns> 249 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded) 250 public bool RemoveTokens(Int64 amount)
160 { 251 {
161 if (maxBurst == 0) 252 // Deposit tokens for this interval
253 Drip();
254
255 // If we have enough tokens then remove them and return
256 if (m_tokenCount - amount >= 0)
162 { 257 {
163 dripSucceeded = true; 258 // we don't have to remove from the parent, the drip rate is already
259 // reflective of the drip rate limits in the parent
260 m_tokenCount -= amount;
164 return true; 261 return true;
165 } 262 }
166 263
167 dripSucceeded = Drip(); 264 return false;
265 }
168 266
169 if (content - amount >= 0) 267 /// <summary>
170 { 268 /// Deposit tokens into the bucket from a child bucket that did
171 if (parent != null && !parent.RemoveTokens(amount)) 269 /// not use all of its available tokens
172 return false; 270 /// </summary>
271 private void Deposit(Int64 count)
272 {
273 m_tokenCount += count;
173 274
174 content -= amount; 275 // Deposit the overflow in the parent bucket, this is how we share
175 return true; 276 // unused bandwidth
176 } 277 Int64 burstrate = BurstRate;
177 else 278 if (m_tokenCount > burstrate)
178 { 279 m_tokenCount = burstrate;
179 return false;
180 }
181 } 280 }
182 281
183 /// <summary> 282 /// <summary>
@@ -186,37 +285,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 /// call to Drip 285 /// call to Drip
187 /// </summary> 286 /// </summary>
188 /// <returns>True if tokens were added to the bucket, otherwise false</returns> 287 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
189 public bool Drip() 288 private void Drip()
190 { 289 {
191 if (tokensPerMS == 0) 290 // This should never happen... means we are a leaf node and were created
291 // with no drip rate...
292 if (DripRate == 0)
192 { 293 {
193 content = maxBurst; 294 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0");
194 return true; 295 return;
195 } 296 }
196 else 297
197 { 298 // Determine the interval over which we are adding tokens, never add
198 int now = Environment.TickCount & Int32.MaxValue; 299 // more than a single quantum of tokens
199 int deltaMS = now - lastDrip; 300 Int32 now = Environment.TickCount & Int32.MaxValue;
301 Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
200 302
201 if (deltaMS <= 0) 303 m_lastDrip = now;
202 {
203 if (deltaMS < 0)
204 lastDrip = now;
205 return false;
206 }
207 304
208 int dripAmount = deltaMS * tokensPerMS; 305 // This can be 0 in the very unusual case that the timer wrapped
306 // It can be 0 if we try add tokens at a sub-tick rate
307 if (deltaMS <= 0)
308 return;
209 309
210 content = Math.Min(content + dripAmount, maxBurst); 310 Deposit(deltaMS * DripRate / m_ticksPerQuantum);
211 lastDrip = now;
212
213 if (dripAmount < 0 || content < 0)
214 // sim has been idle for too long, integer has overflown
215 // previous calculation is meaningless, let's put it at correct max
216 content = maxBurst;
217
218 return true;
219 }
220 } 311 }
221 } 312 }
222} 313}
diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
index 878242a..fc1ddef 100644
--- a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
@@ -54,6 +54,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
54 54
55 private Scene m_scene; 55 private Scene m_scene;
56 private IAssetService m_assetService; 56 private IAssetService m_assetService;
57 private bool m_enabled = true;
57 58
58 #region IRegionModuleBase Members 59 #region IRegionModuleBase Members
59 60
@@ -65,7 +66,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
65 66
66 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
67 { 68 {
68 69 IConfig meshConfig = source.Configs["Mesh"];
70 if (meshConfig == null)
71 return;
72
73 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
69 } 74 }
70 75
71 public void AddRegion(Scene pScene) 76 public void AddRegion(Scene pScene)
@@ -101,16 +106,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
101 106
102 public void RegisterCaps(UUID agentID, Caps caps) 107 public void RegisterCaps(UUID agentID, Caps caps)
103 { 108 {
109 if(!m_enabled)
110 return;
111
104 UUID capID = UUID.Random(); 112 UUID capID = UUID.Random();
105 113
106// m_log.Info("[GETMESH]: /CAPS/" + capID); 114// m_log.Info("[GETMESH]: /CAPS/" + capID);
115
107 caps.RegisterHandler("GetMesh", 116 caps.RegisterHandler("GetMesh",
108 new RestHTTPHandler("GET", "/CAPS/" + capID, 117 new RestHTTPHandler("GET", "/CAPS/" + capID,
109 delegate(Hashtable m_dhttpMethod) 118 delegate(Hashtable m_dhttpMethod)
110 { 119 {
111 return ProcessGetMesh(m_dhttpMethod, agentID, caps); 120 return ProcessGetMesh(m_dhttpMethod, agentID, caps);
112 })); 121 }));
113
114 } 122 }
115 123
116 #endregion 124 #endregion
diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
index 4a42c93..3d4c7b7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
56 private Scene m_scene; 56 private Scene m_scene;
57// private IAssetService m_assetService; 57// private IAssetService m_assetService;
58 private bool m_dumpAssetsToFile = false; 58 private bool m_dumpAssetsToFile = false;
59 private bool m_enabled = true;
59 60
60 #region IRegionModuleBase Members 61 #region IRegionModuleBase Members
61 62
@@ -67,7 +68,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
67 68
68 public void Initialise(IConfigSource source) 69 public void Initialise(IConfigSource source)
69 { 70 {
70 71 IConfig meshConfig = source.Configs["Mesh"];
72 if (meshConfig == null)
73 return;
74
75 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
71 } 76 }
72 77
73 public void AddRegion(Scene pScene) 78 public void AddRegion(Scene pScene)
@@ -103,6 +108,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
103 108
104 public void RegisterCaps(UUID agentID, Caps caps) 109 public void RegisterCaps(UUID agentID, Caps caps)
105 { 110 {
111 if(!m_enabled)
112 return;
113
106 UUID capID = UUID.Random(); 114 UUID capID = UUID.Random();
107 115
108// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID); 116// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 4d74b2a..5baf078 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -34,13 +34,13 @@ using Nini.Config;
34using Nwc.XmlRpc; 34using Nwc.XmlRpc;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Framework.Communications; 38using OpenSim.Framework.Communications;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Friends; 42using OpenSim.Services.Connectors.Friends;
42using OpenSim.Server.Base; 43using OpenSim.Server.Base;
43using OpenSim.Framework.Servers.HttpServer;
44using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; 44using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
45using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 45using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
46using GridRegion = OpenSim.Services.Interfaces.GridRegion; 46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index fdfcd10..919ea33 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -33,7 +33,6 @@ using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Communications; 34using OpenSim.Framework.Communications;
35using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Framework.Client; 36using OpenSim.Framework.Client;
38using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 01170aa..6b24718 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -78,11 +78,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 private Stream m_loadStream; 78 private Stream m_loadStream;
79 79
80 /// <summary> 80 /// <summary>
81 /// FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things 81 /// Has the control file been loaded for this archive?
82 /// (I thought they weren't). We will need to bump the version number and perform this check on all
83 /// subsequent IAR versions only
84 /// </summary> 82 /// </summary>
85 protected bool m_controlFileLoaded = true; 83 public bool ControlFileLoaded { get; private set; }
84
85 /// <summary>
86 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't
87 /// enforce.
88 /// </summary>
89 public bool EnforceControlFileCheck { get; private set; }
90
86 protected bool m_assetsLoaded; 91 protected bool m_assetsLoaded;
87 protected bool m_inventoryNodesLoaded; 92 protected bool m_inventoryNodesLoaded;
88 93
@@ -131,6 +136,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
131 m_userInfo = userInfo; 136 m_userInfo = userInfo;
132 m_invPath = invPath; 137 m_invPath = invPath;
133 m_loadStream = loadStream; 138 m_loadStream = loadStream;
139
140 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things
141 // (I thought they weren't). We will need to bump the version number and perform this check on all
142 // subsequent IAR versions only
143 ControlFileLoaded = true;
134 } 144 }
135 145
136 /// <summary> 146 /// <summary>
@@ -471,16 +481,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
471 if (m_creatorIdForAssetId.ContainsKey(assetId)) 481 if (m_creatorIdForAssetId.ContainsKey(assetId))
472 { 482 {
473 string xmlData = Utils.BytesToString(data); 483 string xmlData = Utils.BytesToString(data);
474 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 484 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
475 foreach (SceneObjectPart sop in sog.Parts) 485
486 CoalescedSceneObjects coa = null;
487 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
488 {
489// m_log.DebugFormat(
490// "[INVENTORY ARCHIVER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
491
492 sceneObjects.AddRange(coa.Objects);
493 }
494 else
476 { 495 {
477 if (sop.CreatorData == null || sop.CreatorData == "") 496 sceneObjects.Add(SceneObjectSerializer.FromOriginalXmlFormat(xmlData));
478 {
479 sop.CreatorID = m_creatorIdForAssetId[assetId];
480 }
481 } 497 }
482 498
483 data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)); 499 foreach (SceneObjectGroup sog in sceneObjects)
500 foreach (SceneObjectPart sop in sog.Parts)
501 if (sop.CreatorData == null || sop.CreatorData == "")
502 sop.CreatorID = m_creatorIdForAssetId[assetId];
503
504 if (coa != null)
505 data = Utils.StringToBytes(CoalescedSceneObjectsSerializer.ToXml(coa));
506 else
507 data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sceneObjects[0]));
484 } 508 }
485 } 509 }
486 510
@@ -508,7 +532,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
508 /// </summary> 532 /// </summary>
509 /// <param name="path"></param> 533 /// <param name="path"></param>
510 /// <param name="data"></param> 534 /// <param name="data"></param>
511 protected void LoadControlFile(string path, byte[] data) 535 public void LoadControlFile(string path, byte[] data)
512 { 536 {
513 XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); 537 XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data));
514 XElement archiveElement = doc.Element("archive"); 538 XElement archiveElement = doc.Element("archive");
@@ -524,7 +548,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
524 majorVersion, MAX_MAJOR_VERSION)); 548 majorVersion, MAX_MAJOR_VERSION));
525 } 549 }
526 550
527 m_controlFileLoaded = true; 551 ControlFileLoaded = true;
528 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); 552 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
529 } 553 }
530 554
@@ -536,7 +560,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
536 /// <param name="data"></param> 560 /// <param name="data"></param>
537 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data) 561 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
538 { 562 {
539 if (!m_controlFileLoaded) 563 if (!ControlFileLoaded)
540 throw new Exception( 564 throw new Exception(
541 string.Format( 565 string.Format(
542 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 566 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
@@ -583,7 +607,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
583 /// <param name="data"></param> 607 /// <param name="data"></param>
584 protected void LoadAssetFile(string path, byte[] data) 608 protected void LoadAssetFile(string path, byte[] data)
585 { 609 {
586 if (!m_controlFileLoaded) 610 if (!ControlFileLoaded)
587 throw new Exception( 611 throw new Exception(
588 string.Format( 612 string.Format(
589 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 613 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index dc4900f..c039b5a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -394,12 +394,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
394 if (options.ContainsKey("profile")) 394 if (options.ContainsKey("profile"))
395 { 395 {
396 majorVersion = 1; 396 majorVersion = 1;
397 minorVersion = 0; 397 minorVersion = 1;
398 } 398 }
399 else 399 else
400 { 400 {
401 majorVersion = 0; 401 majorVersion = 0;
402 minorVersion = 1; 402 minorVersion = 2;
403 } 403 }
404 404
405 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); 405 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index e5127a0..5ba08ee 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -68,17 +68,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
68 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), 68 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"),
69 FirstName = "Mr", 69 FirstName = "Mr",
70 LastName = "Tiddles" }; 70 LastName = "Tiddles" };
71
71 protected UserAccount m_uaLL1 72 protected UserAccount m_uaLL1
72 = new UserAccount { 73 = new UserAccount {
73 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), 74 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"),
74 FirstName = "Lord", 75 FirstName = "Lord",
75 LastName = "Lucan" }; 76 LastName = "Lucan" };
77
76 protected UserAccount m_uaLL2 78 protected UserAccount m_uaLL2
77 = new UserAccount { 79 = new UserAccount {
78 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), 80 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"),
79 FirstName = "Lord", 81 FirstName = "Lord",
80 LastName = "Lucan" }; 82 LastName = "Lucan" };
83
81 protected string m_item1Name = "Ray Gun Item"; 84 protected string m_item1Name = "Ray Gun Item";
85 protected string m_coaItemName = "Coalesced Item";
82 86
83 [SetUp] 87 [SetUp]
84 public virtual void SetUp() 88 public virtual void SetUp()
@@ -97,38 +101,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
97// log4net.Config.XmlConfigurator.Configure(); 101// log4net.Config.XmlConfigurator.Configure();
98 102
99 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 103 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
100 Scene scene = SceneSetupHelpers.SetupScene("Inventory"); 104 Scene scene = SceneSetupHelpers.SetupScene();
101 SceneSetupHelpers.SetupSceneModules(scene, archiverModule); 105 SceneSetupHelpers.SetupSceneModules(scene, archiverModule);
102 106
103 UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 107 UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
104 108
105 MemoryStream archiveWriteStream = new MemoryStream(); 109 MemoryStream archiveWriteStream = new MemoryStream();
106 110
107 // Create asset 111 // Create scene object asset
108 SceneObjectGroup object1; 112 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
109 SceneObjectPart part1; 113 SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50);
110 {
111 string partName = "Ray Gun Object";
112 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
113 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
114 Vector3 groupPosition = new Vector3(10, 20, 30);
115 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
116 Vector3 offsetPosition = new Vector3(5, 10, 15);
117
118 part1
119 = new SceneObjectPart(
120 ownerId, shape, groupPosition, rotationOffset, offsetPosition);
121 part1.Name = partName;
122
123 object1 = new SceneObjectGroup(part1);
124 scene.AddNewSceneObject(object1, false);
125 }
126 114
127 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 115 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
128 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 116 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
129 scene.AssetService.Store(asset1); 117 scene.AssetService.Store(asset1);
130 118
131 // Create item 119 // Create scene object item
132 InventoryItemBase item1 = new InventoryItemBase(); 120 InventoryItemBase item1 = new InventoryItemBase();
133 item1.Name = m_item1Name; 121 item1.Name = m_item1Name;
134 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); 122 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020");
@@ -139,8 +127,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
139 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 127 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
140 scene.AddInventoryItem(item1); 128 scene.AddInventoryItem(item1);
141 129
130 // Create coalesced objects asset
131 SceneObjectGroup cobj1 = SceneSetupHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120);
132 cobj1.AbsolutePosition = new Vector3(15, 30, 45);
133
134 SceneObjectGroup cobj2 = SceneSetupHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140);
135 cobj2.AbsolutePosition = new Vector3(25, 50, 75);
136
137 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2);
138
139 AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa);
140 scene.AssetService.Store(coaAsset);
141
142 // Create coalesced objects inventory item
143 InventoryItemBase coaItem = new InventoryItemBase();
144 coaItem.Name = m_coaItemName;
145 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180");
146 coaItem.AssetID = coaAsset.FullID;
147 coaItem.GroupID = UUID.Random();
148 coaItem.CreatorIdAsUuid = m_uaLL1.PrincipalID;
149 coaItem.Owner = m_uaLL1.PrincipalID;
150 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
151 scene.AddInventoryItem(coaItem);
152
142 archiverModule.ArchiveInventory( 153 archiverModule.ArchiveInventory(
143 Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, m_item1Name, "hampshire", archiveWriteStream); 154 Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream);
144 155
145 m_iarStreamBytes = archiveWriteStream.ToArray(); 156 m_iarStreamBytes = archiveWriteStream.ToArray();
146 } 157 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 7f156f8..52232a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -62,9 +62,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
62 SerialiserModule serialiserModule = new SerialiserModule(); 62 SerialiserModule serialiserModule = new SerialiserModule();
63 m_archiverModule = new InventoryArchiverModule(); 63 m_archiverModule = new InventoryArchiverModule();
64 64
65 m_scene = SceneSetupHelpers.SetupScene("Inventory"); 65 m_scene = SceneSetupHelpers.SetupScene();
66 SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 66 SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
67 } 67 }
68
69 [Test]
70 public void TestLoadCoalesecedItem()
71 {
72 TestHelper.InMethod();
73// log4net.Config.XmlConfigurator.Configure();
74
75 UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password");
76 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
77
78 InventoryItemBase coaItem
79 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName);
80
81 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1");
82
83 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID);
84
85 CoalescedSceneObjects coa;
86 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa);
87
88 Assert.That(readResult, Is.True);
89 Assert.That(coa.Count, Is.EqualTo(2));
90
91 List<SceneObjectGroup> coaObjects = coa.Objects;
92 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120")));
93 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45)));
94
95 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
96 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
97 }
98
99 /// <summary>
100 /// Test that the IAR has the required files in the right order.
101 /// </summary>
102 /// <remarks>
103 /// At the moment, the only thing that matters is that the control file is the very first one.
104 /// </remarks>
105 [Test]
106 public void TestOrder()
107 {
108 TestHelper.InMethod();
109// log4net.Config.XmlConfigurator.Configure();
110
111 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes);
112 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
113 string filePath;
114 TarArchiveReader.TarEntryType tarEntryType;
115
116 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
117 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
118
119 InventoryArchiveReadRequest iarr
120 = new InventoryArchiveReadRequest(null, null, null, (Stream)null, false);
121 iarr.LoadControlFile(filePath, data);
122
123 Assert.That(iarr.ControlFileLoaded, Is.True);
124 }
68 125
69 /// <summary> 126 /// <summary>
70 /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive 127 /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive
@@ -84,24 +141,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
84 UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); 141 UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
85 142
86 // Create asset 143 // Create asset
87 SceneObjectGroup object1; 144 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
88 SceneObjectPart part1; 145 SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50);
89 {
90 string partName = "My Little Dog Object";
91 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
92 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
93 Vector3 groupPosition = new Vector3(10, 20, 30);
94 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
95 Vector3 offsetPosition = new Vector3(5, 10, 15);
96
97 part1
98 = new SceneObjectPart(
99 ownerId, shape, groupPosition, rotationOffset, offsetPosition);
100 part1.Name = partName;
101
102 object1 = new SceneObjectGroup(part1);
103 m_scene.AddNewSceneObject(object1, false);
104 }
105 146
106 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 147 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
107 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 148 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
index 0e8f647..c7dae52 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
63 63
64 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 64 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
65 65
66 Scene scene = SceneSetupHelpers.SetupScene("Inventory"); 66 Scene scene = SceneSetupHelpers.SetupScene();
67 SceneSetupHelpers.SetupSceneModules(scene, archiverModule); 67 SceneSetupHelpers.SetupSceneModules(scene, archiverModule);
68 68
69 // Create user 69 // Create user
@@ -180,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
180 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 180 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
181 181
182 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene 182 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene
183 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 183 Scene scene = SceneSetupHelpers.SetupScene();
184 184
185 SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 185 SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
186 186
@@ -223,7 +223,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
223 223
224 SerialiserModule serialiserModule = new SerialiserModule(); 224 SerialiserModule serialiserModule = new SerialiserModule();
225 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 225 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
226 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 226 Scene scene = SceneSetupHelpers.SetupScene();
227 SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 227 SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
228 228
229 UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password"); 229 UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password");
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
248 248
249 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 249 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
250 250
251 Scene scene = SceneSetupHelpers.SetupScene("Inventory"); 251 Scene scene = SceneSetupHelpers.SetupScene();
252 SceneSetupHelpers.SetupSceneModules(scene, archiverModule); 252 SceneSetupHelpers.SetupSceneModules(scene, archiverModule);
253 253
254 // Create user 254 // Create user
@@ -327,7 +327,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
327 TestHelper.InMethod(); 327 TestHelper.InMethod();
328// log4net.Config.XmlConfigurator.Configure(); 328// log4net.Config.XmlConfigurator.Configure();
329 329
330 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 330 Scene scene = SceneSetupHelpers.SetupScene();
331 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); 331 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
332 332
333 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 333 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
@@ -394,7 +394,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
394 TestHelper.InMethod(); 394 TestHelper.InMethod();
395 //log4net.Config.XmlConfigurator.Configure(); 395 //log4net.Config.XmlConfigurator.Configure();
396 396
397 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 397 Scene scene = SceneSetupHelpers.SetupScene();
398 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); 398 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
399 399
400 string folder1ExistingName = "a"; 400 string folder1ExistingName = "a";
@@ -445,7 +445,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
445 TestHelper.InMethod(); 445 TestHelper.InMethod();
446// log4net.Config.XmlConfigurator.Configure(); 446// log4net.Config.XmlConfigurator.Configure();
447 447
448 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 448 Scene scene = SceneSetupHelpers.SetupScene();
449 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); 449 UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
450 450
451 string folder1ExistingName = "a"; 451 string folder1ExistingName = "a";
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 4565d10..52791cb 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -75,6 +75,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
75 if (name == Name) 75 if (name == Name)
76 { 76 {
77 m_Enabled = true; 77 m_Enabled = true;
78
79 InitialiseCommon(source);
80
78 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name); 81 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
79 82
80 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; 83 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
@@ -129,35 +132,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
129 } 132 }
130 133
131 /// 134 ///
132 /// DeleteToInventory 135 /// Used in DeleteToInventory
133 /// 136 ///
134 public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 137 protected override void ExportAsset(UUID agentID, UUID assetID)
135 { 138 {
136 UUID ret = UUID.Zero;
137
138 // HACK: Only works for lists of length one.
139 // Intermediate version, just to make things compile
140 foreach (SceneObjectGroup g in objectGroups)
141 ret = DeleteToInventory(action, folderID, g, remoteClient);
142
143 return ret;
144 }
145
146 // DO NOT OVERRIDE THE BASE METHOD
147 public new virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
148 SceneObjectGroup objectGroup, IClientAPI remoteClient)
149 {
150 UUID assetID = base.DeleteToInventory(action, folderID, new List<SceneObjectGroup>() {objectGroup}, remoteClient);
151
152 if (!assetID.Equals(UUID.Zero)) 139 if (!assetID.Equals(UUID.Zero))
153 { 140 UploadInventoryItem(agentID, assetID, "", 0);
154 if (remoteClient != null)
155 UploadInventoryItem(remoteClient.AgentId, assetID, "", 0);
156 }
157 else 141 else
158 m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); 142 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
159
160 return assetID;
161 } 143 }
162 144
163 /// 145 ///
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 9fbfc34..6b3df9d 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
64 return m_UserManagement; 64 return m_UserManagement;
65 } 65 }
66 } 66 }
67 67
68 public bool CoalesceMultipleObjectsToInventory { get; set; }
68 69
69 #region INonSharedRegionModule 70 #region INonSharedRegionModule
70 71
@@ -87,10 +88,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
87 if (name == Name) 88 if (name == Name)
88 { 89 {
89 m_Enabled = true; 90 m_Enabled = true;
90 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name); 91
92 InitialiseCommon(source);
93
94 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
91 } 95 }
92 } 96 }
93 } 97 }
98
99 /// <summary>
100 /// Common module config for both this and descendant classes.
101 /// </summary>
102 /// <param name="source"></param>
103 protected virtual void InitialiseCommon(IConfigSource source)
104 {
105 IConfig inventoryConfig = source.Configs["Inventory"];
106
107 if (inventoryConfig != null)
108 CoalesceMultipleObjectsToInventory
109 = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true);
110 else
111 CoalesceMultipleObjectsToInventory = true;
112 }
94 113
95 public virtual void PostInitialise() 114 public virtual void PostInitialise()
96 { 115 {
@@ -194,366 +213,386 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
194 213
195 return UUID.Zero; 214 return UUID.Zero;
196 } 215 }
197 216
198 /// <summary> 217 public virtual UUID CopyToInventory(DeRezAction action, UUID folderID,
199 /// Delete a scene object from a scene and place in the given avatar's inventory.
200 /// Returns the UUID of the newly created asset.
201 /// </summary>
202 /// <param name="action"></param>
203 /// <param name="folderID"></param>
204 /// <param name="objectGroup"></param>
205 /// <param name="remoteClient"> </param>
206 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
207 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 218 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient)
208 { 219 {
209 UUID ret = UUID.Zero; 220 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
210 221
211 // The following code groups the SOG's by owner. No objects 222 if (CoalesceMultipleObjectsToInventory)
212 // belonging to different people can be coalesced, for obvious
213 // reasons.
214 Dictionary<UUID, List<SceneObjectGroup>> deletes =
215 new Dictionary<UUID, List<SceneObjectGroup>>();
216
217 foreach (SceneObjectGroup g in objectGroups)
218 { 223 {
219 if (!deletes.ContainsKey(g.OwnerID)) 224 // The following code groups the SOG's by owner. No objects
220 deletes[g.OwnerID] = new List<SceneObjectGroup>(); 225 // belonging to different people can be coalesced, for obvious
221 226 // reasons.
222 deletes[g.OwnerID].Add(g); 227 foreach (SceneObjectGroup g in objectGroups)
228 {
229 if (!bundlesToCopy.ContainsKey(g.OwnerID))
230 bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>();
231
232 bundlesToCopy[g.OwnerID].Add(g);
233 }
234 }
235 else
236 {
237 // If we don't want to coalesce then put every object in its own bundle.
238 foreach (SceneObjectGroup g in objectGroups)
239 {
240 List<SceneObjectGroup> bundle = new List<SceneObjectGroup>();
241 bundle.Add(g);
242 bundlesToCopy[g.UUID] = bundle;
243 }
223 } 244 }
224 245
225 // This is pethod scoped and will be returned. It will be the 246 // This is method scoped and will be returned. It will be the
226 // last created asset id 247 // last created asset id
227 UUID assetID = UUID.Zero; 248 UUID assetID = UUID.Zero;
228 249
229 // Each iteration is really a separate asset being created, 250 // Each iteration is really a separate asset being created,
230 // with distinct destinations as well. 251 // with distinct destinations as well.
231 foreach (List<SceneObjectGroup> objlist in deletes.Values) 252 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
232 { 253 assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient);
233 Dictionary<UUID, string> xmlStrings = 254
234 new Dictionary<UUID, string>(); 255 return assetID;
235 256 }
236 foreach (SceneObjectGroup objectGroup in objlist) 257
237 { 258 /// <summary>
238 Vector3 inventoryStoredPosition = new Vector3 259 /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object
239 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 260 /// item. If there are multiple objects then these will be saved as a single coalesced item.
240 ? 250 261 /// </summary>
241 : objectGroup.AbsolutePosition.X) 262 /// <param name="action"></param>
242 , 263 /// <param name="folderID"></param>
243 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 264 /// <param name="objlist"></param>
244 ? 250 265 /// <param name="remoteClient"></param>
245 : objectGroup.AbsolutePosition.X, 266 /// <returns></returns>
246 objectGroup.AbsolutePosition.Z); 267 protected UUID CopyBundleToInventory(
247 268 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient)
248 Vector3 originalPosition = objectGroup.AbsolutePosition; 269 {
249 270 UUID assetID = UUID.Zero;
250 objectGroup.AbsolutePosition = inventoryStoredPosition; 271
251 272 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
252 // Make sure all bits but the ones we want are clear 273 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
253 // on take.
254 // This will be applied to the current perms, so
255 // it will do what we want.
256 objectGroup.RootPart.NextOwnerMask &=
257 ((uint)PermissionMask.Copy |
258 (uint)PermissionMask.Transfer |
259 (uint)PermissionMask.Modify);
260 objectGroup.RootPart.NextOwnerMask |=
261 (uint)PermissionMask.Move;
262
263 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
264
265 objectGroup.AbsolutePosition = originalPosition;
266
267 xmlStrings[objectGroup.UUID] = sceneObjectXml;
268 }
269 274
270 string itemXml; 275 foreach (SceneObjectGroup objectGroup in objlist)
276 {
277 Vector3 inventoryStoredPosition = new Vector3
278 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
279 ? 250
280 : objectGroup.AbsolutePosition.X)
281 ,
282 (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize)
283 ? 250
284 : objectGroup.AbsolutePosition.Y,
285 objectGroup.AbsolutePosition.Z);
286
287 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
288
289 objectGroup.AbsolutePosition = inventoryStoredPosition;
290
291 // Make sure all bits but the ones we want are clear
292 // on take.
293 // This will be applied to the current perms, so
294 // it will do what we want.
295 objectGroup.RootPart.NextOwnerMask &=
296 ((uint)PermissionMask.Copy |
297 (uint)PermissionMask.Transfer |
298 (uint)PermissionMask.Modify);
299 objectGroup.RootPart.NextOwnerMask |=
300 (uint)PermissionMask.Move;
301
302 coa.Add(objectGroup);
303 }
271 304
272 if (objlist.Count > 1) 305 string itemXml;
273 {
274 float minX, minY, minZ;
275 float maxX, maxY, maxZ;
276 306
277 Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist, 307 if (objlist.Count > 1)
278 out minX, out maxX, out minY, out maxY, 308 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa);
279 out minZ, out maxZ); 309 else
310 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]);
311
312 // Restore the position of each group now that it has been stored to inventory.
313 foreach (SceneObjectGroup objectGroup in objlist)
314 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
280 315
281 // CreateWrapper 316 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
282 XmlDocument itemDoc = new XmlDocument(); 317 if (item == null)
283 XmlElement root = itemDoc.CreateElement("", "CoalescedObject", ""); 318 return UUID.Zero;
284 itemDoc.AppendChild(root); 319
320 // Can't know creator is the same, so null it in inventory
321 if (objlist.Count > 1)
322 {
323 item.CreatorId = UUID.Zero.ToString();
324 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
325 }
326 else
327 {
328 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
329 item.SaleType = objlist[0].RootPart.ObjectSaleType;
330 item.SalePrice = objlist[0].RootPart.SalePrice;
331 }
332
333 AssetBase asset = CreateAsset(
334 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
335 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
336 (sbyte)AssetType.Object,
337 Utils.StringToBytes(itemXml),
338 objlist[0].OwnerID.ToString());
339 m_Scene.AssetService.Store(asset);
340
341 item.AssetID = asset.FullID;
342 assetID = asset.FullID;
285 343
286 // Embed the offsets into the group XML 344 if (DeRezAction.SaveToExistingUserInventoryItem == action)
287 for ( int i = 0 ; i < objlist.Count ; i++ ) 345 {
288 { 346 m_Scene.InventoryService.UpdateItem(item);
289 XmlDocument doc = new XmlDocument(); 347 }
290 SceneObjectGroup g = objlist[i]; 348 else
291 doc.LoadXml(xmlStrings[g.UUID]); 349 {
292 XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); 350 AddPermissions(item, objlist[0], objlist, remoteClient);
293 e.SetAttribute("offsetx", offsets[i].X.ToString());
294 e.SetAttribute("offsety", offsets[i].Y.ToString());
295 e.SetAttribute("offsetz", offsets[i].Z.ToString());
296
297 XmlNode objectNode = itemDoc.ImportNode(e, true);
298 root.AppendChild(objectNode);
299 }
300 351
301 float sizeX = maxX - minX; 352 item.CreationDate = Util.UnixTimeSinceEpoch();
302 float sizeY = maxY - minY; 353 item.Description = asset.Description;
303 float sizeZ = maxZ - minZ; 354 item.Name = asset.Name;
355 item.AssetType = asset.Type;
304 356
305 root.SetAttribute("x", sizeX.ToString()); 357 m_Scene.AddInventoryItem(item);
306 root.SetAttribute("y", sizeY.ToString());
307 root.SetAttribute("z", sizeZ.ToString());
308 358
309 itemXml = itemDoc.InnerXml; 359 if (remoteClient != null && item.Owner == remoteClient.AgentId)
360 {
361 remoteClient.SendInventoryItemCreateUpdate(item, 0);
310 } 362 }
311 else 363 else
312 { 364 {
313 itemXml = xmlStrings[objlist[0].UUID]; 365 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
366 if (notifyUser != null)
367 {
368 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
369 }
314 } 370 }
371 }
315 372
316 // Get the user info of the item destination 373 // This is a hook to do some per-asset post-processing for subclasses that need that
317 // 374 ExportAsset(remoteClient.AgentId, assetID);
318 UUID userID = UUID.Zero; 375
376 return assetID;
377 }
319 378
320 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || 379 protected virtual void ExportAsset(UUID agentID, UUID assetID)
321 action == DeRezAction.SaveToExistingUserInventoryItem) 380 {
322 { 381 // nothing to do here
323 // Take or take copy require a taker 382 }
324 // Saving changes requires a local user
325 //
326 if (remoteClient == null)
327 return UUID.Zero;
328 383
329 userID = remoteClient.AgentId; 384 /// <summary>
330 } 385 /// Add relevant permissions for an object to the item.
331 else 386 /// </summary>
332 { 387 /// <param name="item"></param>
333 // All returns / deletes go to the object owner 388 /// <param name="so"></param>
334 // 389 /// <param name="objsForEffectivePermissions"></param>
390 /// <param name="remoteClient"></param>
391 /// <returns></returns>
392 protected InventoryItemBase AddPermissions(
393 InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions,
394 IClientAPI remoteClient)
395 {
396 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
397 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
398 effectivePerms &= grp.GetEffectivePermissions();
399 effectivePerms |= (uint)PermissionMask.Move;
335 400
336 userID = objlist[0].RootPart.OwnerID; 401 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
337 } 402 {
403 uint perms = effectivePerms;
404 uint nextPerms = (perms & 7) << 13;
405 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
406 perms &= ~(uint)PermissionMask.Copy;
407 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
408 perms &= ~(uint)PermissionMask.Transfer;
409 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
410 perms &= ~(uint)PermissionMask.Modify;
411
412 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
413 item.CurrentPermissions = item.BasePermissions;
414 item.NextPermissions = perms & so.RootPart.NextOwnerMask;
415 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
416 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
417
418 // Magic number badness. Maybe this deserves an enum.
419 // bit 4 (16) is the "Slam" bit, it means treat as passed
420 // and apply next owner perms on rez
421 item.CurrentPermissions |= 16; // Slam!
422 }
423 else
424 {
425 item.BasePermissions = effectivePerms;
426 item.CurrentPermissions = effectivePerms;
427 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
428 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
429 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
430
431 item.CurrentPermissions &=
432 ((uint)PermissionMask.Copy |
433 (uint)PermissionMask.Transfer |
434 (uint)PermissionMask.Modify |
435 (uint)PermissionMask.Move |
436 7); // Preserve folded permissions
437 }
438
439 return item;
440 }
441
442 /// <summary>
443 /// Create an item using details for the given scene object.
444 /// </summary>
445 /// <param name="action"></param>
446 /// <param name="remoteClient"></param>
447 /// <param name="so"></param>
448 /// <param name="folderID"></param>
449 /// <returns></returns>
450 protected InventoryItemBase CreateItemForObject(
451 DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID)
452 {
453 // Get the user info of the item destination
454 //
455 UUID userID = UUID.Zero;
338 456
339 if (userID == UUID.Zero) // Can't proceed 457 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
340 { 458 action == DeRezAction.SaveToExistingUserInventoryItem)
341 return UUID.Zero; 459 {
342 } 460 // Take or take copy require a taker
461 // Saving changes requires a local user
462 //
463 if (remoteClient == null)
464 return null;
343 465
344 // If we're returning someone's item, it goes back to the 466 userID = remoteClient.AgentId;
345 // owner's Lost And Found folder. 467 }
346 // Delete is treated like return in this case 468 else
347 // Deleting your own items makes them go to trash 469 {
470 // All returns / deletes go to the object owner
348 // 471 //
472 userID = so.RootPart.OwnerID;
473 }
349 474
350 InventoryFolderBase folder = null; 475 if (userID == UUID.Zero) // Can't proceed
351 InventoryItemBase item = null; 476 {
477 return null;
478 }
352 479
353 if (DeRezAction.SaveToExistingUserInventoryItem == action) 480 // If we're returning someone's item, it goes back to the
354 { 481 // owner's Lost And Found folder.
355 item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID); 482 // Delete is treated like return in this case
356 item = m_Scene.InventoryService.GetItem(item); 483 // Deleting your own items makes them go to trash
484 //
485
486 InventoryFolderBase folder = null;
487 InventoryItemBase item = null;
357 488
358 //item = userInfo.RootFolder.FindItem( 489 if (DeRezAction.SaveToExistingUserInventoryItem == action)
359 // objectGroup.RootPart.FromUserInventoryItemID); 490 {
491 item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID);
492 item = m_Scene.InventoryService.GetItem(item);
360 493
361 if (null == item) 494 //item = userInfo.RootFolder.FindItem(
362 { 495 // objectGroup.RootPart.FromUserInventoryItemID);
363 m_log.DebugFormat( 496
364 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", 497 if (null == item)
365 objlist[0].Name, objlist[0].UUID); 498 {
366 return UUID.Zero; 499 m_log.DebugFormat(
367 } 500 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
501 so.Name, so.UUID);
502
503 return null;
368 } 504 }
369 else 505 }
506 else
507 {
508 // Folder magic
509 //
510 if (action == DeRezAction.Delete)
370 { 511 {
371 // Folder magic 512 // Deleting someone else's item
372 // 513 //
373 if (action == DeRezAction.Delete) 514 if (remoteClient == null ||
515 so.OwnerID != remoteClient.AgentId)
374 { 516 {
375 // Deleting someone else's item 517 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
376 //
377 if (remoteClient == null ||
378 objlist[0].OwnerID != remoteClient.AgentId)
379 {
380
381 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
382 }
383 else
384 {
385 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
386 }
387 } 518 }
388 else if (action == DeRezAction.Return) 519 else
389 { 520 {
521 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
522 }
523 }
524 else if (action == DeRezAction.Return)
525 {
526 // Dump to lost + found unconditionally
527 //
528 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
529 }
390 530
391 // Dump to lost + found unconditionally 531 if (folderID == UUID.Zero && folder == null)
532 {
533 if (action == DeRezAction.Delete)
534 {
535 // Deletes go to trash by default
392 // 536 //
393 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 537 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
394 } 538 }
395 539 else
396 if (folderID == UUID.Zero && folder == null)
397 { 540 {
398 if (action == DeRezAction.Delete) 541 if (remoteClient == null || so.OwnerID != remoteClient.AgentId)
399 { 542 {
400 // Deletes go to trash by default 543 // Taking copy of another person's item. Take to
401 // 544 // Objects folder.
402 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); 545 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
403 } 546 }
404 else 547 else
405 { 548 {
406 if (remoteClient == null || 549 // Catch all. Use lost & found
407 objlist[0].OwnerID != remoteClient.AgentId) 550 //
408 {
409 // Taking copy of another person's item. Take to
410 // Objects folder.
411 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
412 }
413 else
414 {
415 // Catch all. Use lost & found
416 //
417
418 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
419 }
420 }
421 }
422
423 // Override and put into where it came from, if it came
424 // from anywhere in inventory
425 //
426 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
427 {
428 if (objlist[0].RootPart.FromFolderID != UUID.Zero)
429 {
430 InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID);
431 folder = m_Scene.InventoryService.GetFolder(f);
432 }
433 }
434
435 if (folder == null) // None of the above
436 {
437 folder = new InventoryFolderBase(folderID);
438 551
439 if (folder == null) // Nowhere to put it 552 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
440 {
441 return UUID.Zero;
442 } 553 }
443 } 554 }
444
445 item = new InventoryItemBase();
446 // Can't know creator is the same, so null it in inventory
447 if (objlist.Count > 1)
448 item.CreatorId = UUID.Zero.ToString();
449 else
450 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
451 item.ID = UUID.Random();
452 item.InvType = (int)InventoryType.Object;
453 item.Folder = folder.ID;
454 item.Owner = userID;
455 if (objlist.Count > 1)
456 {
457 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
458 }
459 else
460 {
461 item.SaleType = objlist[0].RootPart.ObjectSaleType;
462 item.SalePrice = objlist[0].RootPart.SalePrice;
463 }
464 } 555 }
465 556
466 AssetBase asset = CreateAsset( 557 // Override and put into where it came from, if it came
467 objlist[0].GetPartName(objlist[0].RootPart.LocalId), 558 // from anywhere in inventory
468 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), 559 //
469 (sbyte)AssetType.Object, 560 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
470 Utils.StringToBytes(itemXml),
471 objlist[0].OwnerID.ToString());
472 m_Scene.AssetService.Store(asset);
473 assetID = asset.FullID;
474
475 if (DeRezAction.SaveToExistingUserInventoryItem == action)
476 {
477 item.AssetID = asset.FullID;
478 m_Scene.InventoryService.UpdateItem(item);
479 }
480 else
481 { 561 {
482 item.AssetID = asset.FullID; 562 if (so.RootPart.FromFolderID != UUID.Zero)
483
484 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
485 foreach (SceneObjectGroup grp in objlist)
486 effectivePerms &= grp.GetEffectivePermissions();
487 effectivePerms |= (uint)PermissionMask.Move;
488
489 if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
490 { 563 {
491 uint perms = effectivePerms; 564 InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID);
492 uint nextPerms = (perms & 7) << 13; 565 folder = m_Scene.InventoryService.GetFolder(f);
493 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
494 perms &= ~(uint)PermissionMask.Copy;
495 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
496 perms &= ~(uint)PermissionMask.Transfer;
497 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
498 perms &= ~(uint)PermissionMask.Modify;
499
500 item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask;
501 item.CurrentPermissions = item.BasePermissions;
502 item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask;
503 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask;
504 item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask;
505
506 // Magic number badness. Maybe this deserves an enum.
507 // bit 4 (16) is the "Slam" bit, it means treat as passed
508 // and apply next owner perms on rez
509 item.CurrentPermissions |= 16; // Slam!
510 } 566 }
511 else 567 }
512 {
513 item.BasePermissions = effectivePerms;
514 item.CurrentPermissions = effectivePerms;
515 item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms;
516 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms;
517 item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms;
518
519 item.CurrentPermissions &=
520 ((uint)PermissionMask.Copy |
521 (uint)PermissionMask.Transfer |
522 (uint)PermissionMask.Modify |
523 (uint)PermissionMask.Move |
524 7); // Preserve folded permissions
525 }
526
527 item.CreationDate = Util.UnixTimeSinceEpoch();
528 item.Description = asset.Description;
529 item.Name = asset.Name;
530 item.AssetType = asset.Type;
531 568
532 m_Scene.AddInventoryItem(item); 569 if (folder == null) // None of the above
570 {
571 folder = new InventoryFolderBase(folderID);
533 572
534 if (remoteClient != null && item.Owner == remoteClient.AgentId) 573 if (folder == null) // Nowhere to put it
535 {
536 remoteClient.SendInventoryItemCreateUpdate(item, 0);
537 }
538 else
539 { 574 {
540 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); 575 return null;
541 if (notifyUser != null)
542 {
543 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
544 }
545 } 576 }
546 } 577 }
547 }
548 return assetID;
549 }
550 578
579 item = new InventoryItemBase();
580 item.ID = UUID.Random();
581 item.InvType = (int)InventoryType.Object;
582 item.Folder = folder.ID;
583 item.Owner = userID;
584 }
585
586 return item;
587 }
551 588
552 /// <summary> 589 /// <summary>
553 /// Rez an object into the scene from the user's inventory 590 /// Rez an object into the scene from the user's inventory
554 /// </summary> 591 /// </summary>
592 /// <remarks>
555 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing 593 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing
556 /// things to the scene. The caller should be doing that, I think. 594 /// things to the scene. The caller should be doing that, I think.
595 /// </remarks>
557 /// <param name="remoteClient"></param> 596 /// <param name="remoteClient"></param>
558 /// <param name="itemID"></param> 597 /// <param name="itemID"></param>
559 /// <param name="RayEnd"></param> 598 /// <param name="RayEnd"></param>
@@ -570,21 +609,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
570 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 609 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
571 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 610 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
572 { 611 {
573 // Work out position details 612// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
574 byte bRayEndIsIntersection = (byte)0; 613
575 614 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
576 if (RayEndIsIntersection)
577 {
578 bRayEndIsIntersection = (byte)1;
579 }
580 else
581 {
582 bRayEndIsIntersection = (byte)0;
583 }
584
585 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); 615 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
586
587
588 Vector3 pos = m_Scene.GetNewRezLocation( 616 Vector3 pos = m_Scene.GetNewRezLocation(
589 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 617 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
590 BypassRayCast, bRayEndIsIntersection, true, scale, false); 618 BypassRayCast, bRayEndIsIntersection, true, scale, false);
@@ -668,9 +696,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
668 itemId, n.OuterXml); 696 itemId, n.OuterXml);
669 objlist.Add(g); 697 objlist.Add(g);
670 XmlElement el = (XmlElement)n; 698 XmlElement el = (XmlElement)n;
671 float x = Convert.ToSingle(el.GetAttribute("offsetx")); 699
672 float y = Convert.ToSingle(el.GetAttribute("offsety")); 700 string rawX = el.GetAttribute("offsetx");
673 float z = Convert.ToSingle(el.GetAttribute("offsetz")); 701 string rawY = el.GetAttribute("offsety");
702 string rawZ = el.GetAttribute("offsetz");
703//
704// m_log.DebugFormat(
705// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
706// g.Name, rawX, rawY, rawZ);
707
708 float x = Convert.ToSingle(rawX);
709 float y = Convert.ToSingle(rawY);
710 float z = Convert.ToSingle(rawZ);
674 veclist.Add(new Vector3(x, y, z)); 711 veclist.Add(new Vector3(x, y, z));
675 } 712 }
676 } 713 }
@@ -762,10 +799,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
762 // affect the name stored in the serialization, transfer 799 // affect the name stored in the serialization, transfer
763 // the correct name from the inventory to the 800 // the correct name from the inventory to the
764 // object itself before we rez. 801 // object itself before we rez.
765 rootPart.Name = item.Name; 802 //
766 rootPart.Description = item.Description; 803 // Only do these for the first object if we are rezzing a coalescence.
767 rootPart.ObjectSaleType = item.SaleType; 804 if (i == 0)
768 rootPart.SalePrice = item.SalePrice; 805 {
806 rootPart.Name = item.Name;
807 rootPart.Description = item.Description;
808 rootPart.ObjectSaleType = item.SaleType;
809 rootPart.SalePrice = item.SalePrice;
810 }
769 811
770 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 812 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
771 if ((rootPart.OwnerID != item.Owner) || 813 if ((rootPart.OwnerID != item.Owner) ||
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
new file mode 100644
index 0000000..8d53cf1
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -0,0 +1,174 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Threading;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Framework;
38using OpenSim.Framework.Serialization;
39using OpenSim.Framework.Serialization.External;
40using OpenSim.Framework.Communications;
41using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
42using OpenSim.Region.CoreModules.Framework.InventoryAccess;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common;
47using OpenSim.Tests.Common.Mock;
48using OpenSim.Tests.Common.Setup;
49
50namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
51{
52 [TestFixture]
53 public class InventoryAccessModuleTests
54 {
55 protected TestScene m_scene;
56 protected BasicInventoryAccessModule m_iam;
57 protected UUID m_userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
58 protected TestClient m_tc;
59
60 [SetUp]
61 public void SetUp()
62 {
63 m_iam = new BasicInventoryAccessModule();
64
65 IConfigSource config = new IniConfigSource();
66 config.AddConfig("Modules");
67 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
68
69 m_scene = SceneSetupHelpers.SetupScene();
70 SceneSetupHelpers.SetupSceneModules(m_scene, config, m_iam);
71
72 // Create user
73 string userFirstName = "Jock";
74 string userLastName = "Stirrup";
75 string userPassword = "troll";
76 UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword);
77
78 AgentCircuitData acd = new AgentCircuitData();
79 acd.AgentID = m_userId;
80 m_tc = new TestClient(acd, m_scene);
81 }
82
83 [Test]
84 public void TestRezCoalescedObject()
85 {
86 TestHelper.InMethod();
87// log4net.Config.XmlConfigurator.Configure();
88
89 // Create asset
90 SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20);
91 object1.AbsolutePosition = new Vector3(15, 30, 45);
92
93 SceneObjectGroup object2 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40);
94 object2.AbsolutePosition = new Vector3(25, 50, 75);
95
96 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2);
97
98 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
99 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, coa);
100 m_scene.AssetService.Store(asset1);
101
102 // Create item
103 UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080");
104 string item1Name = "My Little Dog";
105 InventoryItemBase item1 = new InventoryItemBase();
106 item1.Name = item1Name;
107 item1.AssetID = asset1.FullID;
108 item1.ID = item1Id;
109 InventoryFolderBase objsFolder
110 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0];
111 item1.Folder = objsFolder.ID;
112 m_scene.AddInventoryItem(item1);
113
114 SceneObjectGroup so
115 = m_iam.RezObject(
116 m_tc, item1Id, new Vector3(100, 100, 100), Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false);
117
118 Assert.That(so, Is.Not.Null);
119
120 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(2));
121
122 SceneObjectPart retrievedObj1Part = m_scene.GetSceneObjectPart(object1.Name);
123 Assert.That(retrievedObj1Part, Is.Null);
124
125 retrievedObj1Part = m_scene.GetSceneObjectPart(item1.Name);
126 Assert.That(retrievedObj1Part, Is.Not.Null);
127 Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name));
128
129 // Bottom of coalescence is placed on ground, hence we end up with 100.5 rather than 85 since the bottom
130 // object is unit square.
131 Assert.That(retrievedObj1Part.AbsolutePosition, Is.EqualTo(new Vector3(95, 90, 100.5f)));
132
133 SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name);
134 Assert.That(retrievedObj2Part, Is.Not.Null);
135 Assert.That(retrievedObj2Part.Name, Is.EqualTo(object2.Name));
136 Assert.That(retrievedObj2Part.AbsolutePosition, Is.EqualTo(new Vector3(105, 110, 130.5f)));
137 }
138
139 [Test]
140 public void TestRezObject()
141 {
142 TestHelper.InMethod();
143// log4net.Config.XmlConfigurator.Configure();
144
145 // Create asset
146 SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, m_userId, "My Little Dog Object", 0x40);
147
148 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
149 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
150 m_scene.AssetService.Store(asset1);
151
152 // Create item
153 UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080");
154 string item1Name = "My Little Dog";
155 InventoryItemBase item1 = new InventoryItemBase();
156 item1.Name = item1Name;
157 item1.AssetID = asset1.FullID;
158 item1.ID = item1Id;
159 InventoryFolderBase objsFolder
160 = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, m_userId, "Objects")[0];
161 item1.Folder = objsFolder.ID;
162 m_scene.AddInventoryItem(item1);
163
164 SceneObjectGroup so
165 = m_iam.RezObject(
166 m_tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false);
167
168 Assert.That(so, Is.Not.Null);
169
170 SceneObjectPart retrievedPart = m_scene.GetSceneObjectPart(so.UUID);
171 Assert.That(retrievedPart, Is.Not.Null);
172 }
173 }
174} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index d78931a..4c8424d 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -29,8 +29,10 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Net.Security;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
35using System.Security.Cryptography.X509Certificates;
34using Nini.Config; 36using Nini.Config;
35using OpenMetaverse; 37using OpenMetaverse;
36using OpenSim.Framework; 38using OpenSim.Framework;
@@ -100,8 +102,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
100 102
101 public HttpRequestModule() 103 public HttpRequestModule()
102 { 104 {
105 ServicePointManager.ServerCertificateValidationCallback +=ValidateServerCertificate;
103 } 106 }
104 107
108 public static bool ValidateServerCertificate(
109 object sender,
110 X509Certificate certificate,
111 X509Chain chain,
112 SslPolicyErrors sslPolicyErrors)
113 {
114 HttpWebRequest Request = (HttpWebRequest)sender;
115
116 if (Request.Headers.Get("NoVerifyCert") != null)
117 {
118 return true;
119 }
120
121 return chain.Build(new X509Certificate2(certificate));
122 }
105 #region IHttpRequestModule Members 123 #region IHttpRequestModule Members
106 124
107 public UUID MakeHttpRequest(string url, string parameters, string body) 125 public UUID MakeHttpRequest(string url, string parameters, string body)
@@ -141,8 +159,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
141 break; 159 break;
142 160
143 case (int)HttpRequestConstants.HTTP_VERIFY_CERT: 161 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
144 162 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
145 // TODO implement me
146 break; 163 break;
147 } 164 }
148 } 165 }
@@ -189,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
189 * Not sure how important ordering is is here - the next first 206 * Not sure how important ordering is is here - the next first
190 * one completed in the list is returned, based soley on its list 207 * one completed in the list is returned, based soley on its list
191 * position, not the order in which the request was started or 208 * position, not the order in which the request was started or
192 * finsihed. I thought about setting up a queue for this, but 209 * finished. I thought about setting up a queue for this, but
193 * it will need some refactoring and this works 'enough' right now 210 * it will need some refactoring and this works 'enough' right now
194 */ 211 */
195 212
@@ -237,8 +254,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
237 254
238 m_scene.RegisterModuleInterface<IHttpRequestModule>(this); 255 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
239 256
240 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 257 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
241 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 258 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
242 259
243 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 260 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
244 } 261 }
@@ -282,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
282 public string HttpMethod = "GET"; 299 public string HttpMethod = "GET";
283 public string HttpMIMEType = "text/plain;charset=utf-8"; 300 public string HttpMIMEType = "text/plain;charset=utf-8";
284 public int HttpTimeout; 301 public int HttpTimeout;
285 // public bool HttpVerifyCert = true; // not implemented 302 public bool HttpVerifyCert = true;
286 private Thread httpThread; 303 private Thread httpThread;
287 304
288 // Request info 305 // Request info
@@ -344,6 +361,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
344 Request.Method = HttpMethod; 361 Request.Method = HttpMethod;
345 Request.ContentType = HttpMIMEType; 362 Request.ContentType = HttpMIMEType;
346 363
364 if(!HttpVerifyCert)
365 {
366 // We could hijack Connection Group Name to identify
367 // a desired security exception. But at the moment we'll use a dummy header instead.
368// Request.ConnectionGroupName = "NoVerify";
369 Request.Headers.Add("NoVerifyCert", "true");
370 }
371// else
372// {
373// Request.ConnectionGroupName="Verify";
374// }
347 if (proxyurl != null && proxyurl.Length > 0) 375 if (proxyurl != null && proxyurl.Length > 0)
348 { 376 {
349 if (proxyexcepts != null && proxyexcepts.Length > 0) 377 if (proxyexcepts != null && proxyexcepts.Length > 0)
@@ -436,4 +464,4 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
436 } 464 }
437 } 465 }
438 } 466 }
439} 467} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
index e25700d..422f394 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
index 02acddc..2b5beba 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
index 6d975af..f29c074 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index 2f96bcb..d2343c9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
index 209cf0d..53a8ace 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
@@ -31,9 +31,8 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
38using OpenSim.Server.Handlers.Base; 37using OpenSim.Server.Handlers.Base;
39 38
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
index fcc69e9..fc64203 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
index 2a9366c..f759470 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
index 35518d5..5c32632 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
index 5ee1c97..86b4926 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base; 36using OpenSim.Server.Base;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 1b3419d..51d1d59 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -195,6 +195,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
195 195
196 public byte[] GetData(string id) 196 public byte[] GetData(string id)
197 { 197 {
198// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
199
198 AssetBase asset = m_Cache.Get(id); 200 AssetBase asset = m_Cache.Get(id);
199 201
200 if (asset != null) 202 if (asset != null)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fd8f546..82bef48 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -57,6 +57,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
57 /// bumps here should be compatible. 57 /// bumps here should be compatible.
58 /// </summary> 58 /// </summary>
59 public static int MAX_MAJOR_VERSION = 1; 59 public static int MAX_MAJOR_VERSION = 1;
60
61 /// <summary>
62 /// Has the control file been loaded for this archive?
63 /// </summary>
64 public bool ControlFileLoaded { get; private set; }
60 65
61 protected Scene m_scene; 66 protected Scene m_scene;
62 protected Stream m_loadStream; 67 protected Stream m_loadStream;
@@ -527,7 +532,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
527 /// </summary> 532 /// </summary>
528 /// <param name="path"></param> 533 /// <param name="path"></param>
529 /// <param name="data"></param> 534 /// <param name="data"></param>
530 protected void LoadControlFile(string path, byte[] data) 535 public void LoadControlFile(string path, byte[] data)
531 { 536 {
532 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 537 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
533 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 538 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
@@ -573,6 +578,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
573 } 578 }
574 579
575 currentRegionSettings.Save(); 580 currentRegionSettings.Save();
581
582 ControlFileLoaded = true;
576 } 583 }
577 } 584 }
578} \ No newline at end of file 585} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index f2d487e..597b780 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
206 /// <returns></returns> 206 /// <returns></returns>
207 public static string CreateControlFile(Dictionary<string, object> options) 207 public static string CreateControlFile(Dictionary<string, object> options)
208 { 208 {
209 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 5; 209 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6;
210// 210//
211// if (options.ContainsKey("version")) 211// if (options.ContainsKey("version"))
212// { 212// {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index e2760a2..2307c8e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -171,7 +171,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
171 MemoryStream archiveReadStream = new MemoryStream(archive); 171 MemoryStream archiveReadStream = new MemoryStream(archive);
172 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 172 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
173 173
174 bool gotControlFile = false;
175 bool gotNcAssetFile = false; 174 bool gotNcAssetFile = false;
176 175
177 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt"); 176 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt");
@@ -182,15 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
182 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 181 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
183 182
184 string filePath; 183 string filePath;
185 TarArchiveReader.TarEntryType tarEntryType; 184 TarArchiveReader.TarEntryType tarEntryType;
186 185
186 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
187 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
188
189 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
190 arr.LoadControlFile(filePath, data);
191
192 Assert.That(arr.ControlFileLoaded, Is.True);
193
187 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 194 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
188 { 195 {
189 if (ArchiveConstants.CONTROL_FILE_PATH == filePath) 196 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
190 {
191 gotControlFile = true;
192 }
193 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
194 { 197 {
195 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); 198 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
196 199
@@ -203,7 +206,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
203 } 206 }
204 } 207 }
205 208
206 Assert.That(gotControlFile, Is.True, "No control file in archive");
207 Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive"); 209 Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive");
208 Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); 210 Assert.That(foundPaths, Is.EquivalentTo(expectedPaths));
209 211
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index b6d64ac..3aed6ba 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -125,7 +125,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
125 else 125 else
126 Scene.RegionInfo.RegionSettings.AllowLandResell = true; 126 Scene.RegionInfo.RegionSettings.AllowLandResell = true;
127 127
128 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; 128 if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity)
129 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
130 else
131 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity;
129 132
130 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; 133 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
131 134
@@ -259,6 +262,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
259 262
260 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) 263 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID)
261 { 264 {
265// m_log.DebugFormat(
266// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}",
267// remoteClient.Name, estateCovenantID);
268
262 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; 269 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID;
263 Scene.RegionInfo.RegionSettings.Save(); 270 Scene.RegionInfo.RegionSettings.Save();
264 TriggerRegionInfoChange(); 271 TriggerRegionInfoChange();
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index dafaa0c..a866fd9 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -237,7 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
237 public void Init() 237 public void Init()
238 { 238 {
239 m_serialiserModule = new SerialiserModule(); 239 m_serialiserModule = new SerialiserModule();
240 m_scene = SceneSetupHelpers.SetupScene(""); 240 m_scene = SceneSetupHelpers.SetupScene();
241 SceneSetupHelpers.SetupSceneModules(m_scene, m_serialiserModule); 241 SceneSetupHelpers.SetupSceneModules(m_scene, m_serialiserModule);
242 } 242 }
243 243
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d6fa093..21a9999 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -124,6 +124,52 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
124 colours.Save(stream, ImageFormat.Png); 124 colours.Save(stream, ImageFormat.Png);
125 } 125 }
126 126
127 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
128 int offsetX, int offsetY,
129 int fileWidth, int fileHeight,
130 int regionSizeX, int regionSizeY)
131
132 {
133 // We need to do this because:
134 // "Saving the image to the same file it was constructed from is not allowed and throws an exception."
135 string tempName = offsetX + "_ " + offsetY + "_" + filename;
136
137 Bitmap entireBitmap = null;
138 Bitmap thisBitmap = null;
139 if (File.Exists(filename))
140 {
141 File.Copy(filename, tempName);
142 entireBitmap = new Bitmap(tempName);
143 if (entireBitmap.Width != fileWidth * regionSizeX || entireBitmap.Height != fileHeight * regionSizeY)
144 {
145 // old file, let's overwrite it
146 entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
147 }
148 }
149 else
150 {
151 entireBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
152 }
153
154 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
155 Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
156 for (int x = 0; x < regionSizeX; x++)
157 for (int y = 0; y < regionSizeY; y++)
158 entireBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
159
160 Save(entireBitmap, filename);
161 thisBitmap.Dispose();
162 entireBitmap.Dispose();
163
164 if (File.Exists(tempName))
165 File.Delete(tempName);
166 }
167
168 protected virtual void Save(Bitmap bmp, string filename)
169 {
170 bmp.Save(filename, ImageFormat.Png);
171 }
172
127 #endregion 173 #endregion
128 174
129 public override string ToString() 175 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
index 8667607..1a0d8ec 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
@@ -76,6 +76,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
76 colours.Save(stream, ImageFormat.Jpeg); 76 colours.Save(stream, ImageFormat.Jpeg);
77 } 77 }
78 78
79 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
80 int offsetX, int offsetY,
81 int fileWidth, int fileHeight,
82 int regionSizeX, int regionSizeY)
83 {
84 throw new System.Exception("Not Implemented");
85 }
86
79 #endregion 87 #endregion
80 88
81 public override string ToString() 89 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
index a70ef13..fad7641 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
@@ -240,6 +240,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
240 get { return ".raw"; } 240 get { return ".raw"; }
241 } 241 }
242 242
243 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
244 int offsetX, int offsetY,
245 int fileWidth, int fileHeight,
246 int regionSizeX, int regionSizeY)
247 {
248 throw new System.Exception("Not Implemented");
249 }
250
243 #endregion 251 #endregion
244 252
245 public override string ToString() 253 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs
index 3c76665..ba073ca 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs
@@ -160,6 +160,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
160 bs.Close(); 160 bs.Close();
161 } 161 }
162 162
163 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
164 int offsetX, int offsetY,
165 int fileWidth, int fileHeight,
166 int regionSizeX, int regionSizeY)
167 {
168 throw new System.Exception("Not Implemented");
169 }
163 #endregion 170 #endregion
164 171
165 public override string ToString() 172 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
index 2919897..2f37d9d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs
@@ -308,6 +308,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
308 get { return ".ter"; } 308 get { return ".ter"; }
309 } 309 }
310 310
311 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
312 int offsetX, int offsetY,
313 int fileWidth, int fileHeight,
314 int regionSizeX, int regionSizeY)
315 {
316 throw new System.Exception("Not Implemented");
317 }
318
311 #endregion 319 #endregion
312 320
313 public override string ToString() 321 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
index 7403281..7237f90 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
@@ -38,5 +38,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
38 ITerrainChannel LoadStream(Stream stream); 38 ITerrainChannel LoadStream(Stream stream);
39 void SaveFile(string filename, ITerrainChannel map); 39 void SaveFile(string filename, ITerrainChannel map);
40 void SaveStream(Stream stream, ITerrainChannel map); 40 void SaveStream(Stream stream, ITerrainChannel map);
41 void SaveFile(ITerrainChannel map, string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int regionSizeX, int regionSizeY);
41 } 42 }
42} \ No newline at end of file 43} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 8a79d78..9c7b2fa 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -541,6 +541,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain
541 } 541 }
542 542
543 /// <summary> 543 /// <summary>
544 /// Saves the terrain to a larger terrain file.
545 /// </summary>
546 /// <param name="filename">The terrain file to save</param>
547 /// <param name="fileWidth">The width of the file in units</param>
548 /// <param name="fileHeight">The height of the file in units</param>
549 /// <param name="fileStartX">Where to begin our slice</param>
550 /// <param name="fileStartY">Where to begin our slice</param>
551 public void SaveToFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
552 {
553 int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX;
554 int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY;
555
556 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
557 {
558 // this region is included in the tile request
559 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
560 {
561 if (filename.EndsWith(loader.Key))
562 {
563 lock (m_scene)
564 {
565 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
566 fileWidth, fileHeight,
567 (int)Constants.RegionSize,
568 (int)Constants.RegionSize);
569 }
570 return;
571 }
572 }
573 }
574 }
575
576 /// <summary>
544 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections 577 /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
545 /// </summary> 578 /// </summary>
546 private void EventManager_OnTerrainTick() 579 private void EventManager_OnTerrainTick()
@@ -860,6 +893,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
860 SaveToFile((string) args[0]); 893 SaveToFile((string) args[0]);
861 } 894 }
862 895
896 private void InterfaceSaveTileFile(Object[] args)
897 {
898 SaveToFile((string)args[0],
899 (int)args[1],
900 (int)args[2],
901 (int)args[3],
902 (int)args[4]);
903 }
904
863 private void InterfaceBakeTerrain(Object[] args) 905 private void InterfaceBakeTerrain(Object[] args)
864 { 906 {
865 UpdateRevertMap(); 907 UpdateRevertMap();
@@ -1115,6 +1157,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1115 loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", 1157 loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file",
1116 "Integer"); 1158 "Integer");
1117 1159
1160 Command saveToTileCommand =
1161 new Command("save-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceSaveTileFile, "Saves the current heightmap to the larger file.");
1162 saveToTileCommand.AddArgument("filename",
1163 "The file you wish to save to, the file extension determines the loader to be used. Supported extensions include: " +
1164 supportedFileExtensions, "String");
1165 saveToTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer");
1166 saveToTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer");
1167 saveToTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file",
1168 "Integer");
1169 saveToTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file",
1170 "Integer");
1118 // Terrain adjustments 1171 // Terrain adjustments
1119 Command fillRegionCommand = 1172 Command fillRegionCommand =
1120 new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value."); 1173 new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value.");
@@ -1166,6 +1219,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1166 m_commander.RegisterCommand("load", loadFromFileCommand); 1219 m_commander.RegisterCommand("load", loadFromFileCommand);
1167 m_commander.RegisterCommand("load-tile", loadFromTileCommand); 1220 m_commander.RegisterCommand("load-tile", loadFromTileCommand);
1168 m_commander.RegisterCommand("save", saveToFileCommand); 1221 m_commander.RegisterCommand("save", saveToFileCommand);
1222 m_commander.RegisterCommand("save-tile", saveToTileCommand);
1169 m_commander.RegisterCommand("fill", fillRegionCommand); 1223 m_commander.RegisterCommand("fill", fillRegionCommand);
1170 m_commander.RegisterCommand("elevate", elevateCommand); 1224 m_commander.RegisterCommand("elevate", elevateCommand);
1171 m_commander.RegisterCommand("lower", lowerCommand); 1225 m_commander.RegisterCommand("lower", lowerCommand);
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index d939329..89e9e20 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -702,18 +702,12 @@ namespace OpenSim.Region.Examples.SimpleModule
702 { 702 {
703 } 703 }
704 704
705 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, 705 public void SendObjectPropertiesFamilyData(ISceneEntity Entity, uint RequestFlags)
706 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
707 uint NextOwnerMask, int OwnershipCost, byte SaleType,int SalePrice, uint Category,
708 UUID LastOwnerID, string ObjectName, string Description)
709 { 706 {
707
710 } 708 }
711 709
712 public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, 710 public void SendObjectPropertiesReply(ISceneEntity entity)
713 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
714 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
715 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
716 uint BaseMask, byte saleType, int salePrice)
717 { 711 {
718 } 712 }
719 713
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
index 05fc2ad..305975e 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
@@ -38,7 +38,23 @@ namespace OpenSim.Region.Framework.Interfaces
38 public interface IInventoryAccessModule 38 public interface IInventoryAccessModule
39 { 39 {
40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data); 40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data);
41 UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient); 41
42 /// <summary>
43 /// Copy objects to a user's inventory.
44 /// </summary>
45 /// <remarks>
46 /// Is it left to the caller to delete them from the scene if required.
47 /// </remarks>
48 /// <param name="action"></param>
49 /// <param name="folderID"></param>
50 /// <param name="objectGroups"></param>
51 /// <param name="remoteClient"></param>
52 /// <returns>
53 /// Returns the UUID of the newly created item asset (not the item itself).
54 /// FIXME: This is not very useful. It would be far more useful to return a list of items instead.
55 /// </returns>
56 UUID CopyToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient);
57
42 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 58 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
43 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 59 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
44 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); 60 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 23be9c2..14ecd44 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -223,7 +223,8 @@ namespace OpenSim.Region.Framework
223 catch (Exception e) 223 catch (Exception e)
224 { 224 {
225 m_log.ErrorFormat( 225 m_log.ErrorFormat(
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for plugin DLL {0}. Exception {1} {2}",
227 pluginAssembly.FullName, e.Message, e.StackTrace);
227 228
228 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
229 throw e; 230 throw e;
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 8feb022..3423542 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -143,7 +143,8 @@ namespace OpenSim.Region.Framework.Scenes
143 { 143 {
144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
145 if (invAccess != null) 145 if (invAccess != null)
146 invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); 146 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient);
147
147 if (x.permissionToDelete) 148 if (x.permissionToDelete)
148 { 149 {
149 foreach (SceneObjectGroup g in x.objectGroups) 150 foreach (SceneObjectGroup g in x.objectGroups)
diff --git a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
new file mode 100644
index 0000000..af8ccda
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
@@ -0,0 +1,154 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 /// <summary>
36 /// Represents a coalescene of scene objects. A coalescence occurs when objects that are not in the same linkset
37 /// are grouped together.
38 /// </summary>
39 public class CoalescedSceneObjects
40 {
41 /// <summary>
42 /// The creator of this coalesence, though not necessarily the objects within it.
43 /// </summary>
44 public UUID CreatorId { get; set; }
45
46 /// <summary>
47 /// The number of objects in this coalesence
48 /// </summary>
49 public int Count
50 {
51 get
52 {
53 lock (m_memberObjects)
54 return m_memberObjects.Count;
55 }
56 }
57
58 /// <summary>
59 /// Does this coalesence have any member objects?
60 /// </summary>
61 public bool HasObjects { get { return Count > 0; } }
62
63 /// <summary>
64 /// Get the objects currently in this coalescence
65 /// </summary>
66 public List<SceneObjectGroup> Objects
67 {
68 get
69 {
70 lock (m_memberObjects)
71 return new List<SceneObjectGroup>(m_memberObjects);
72 }
73 }
74
75 /// <summary>
76 /// Get the scene that contains the objects in this coalescence. If there are no objects then null is returned.
77 /// </summary>
78 public Scene Scene
79 {
80 get
81 {
82 if (!HasObjects)
83 return null;
84 else
85 return Objects[0].Scene;
86 }
87 }
88
89 /// <summary>
90 /// At this point, we need to preserve the order of objects added to the coalescence, since the first
91 /// one will end up matching the item name when rerezzed.
92 /// </summary>
93 protected List<SceneObjectGroup> m_memberObjects = new List<SceneObjectGroup>();
94
95 public CoalescedSceneObjects(UUID creatorId)
96 {
97 CreatorId = creatorId;
98 }
99
100 public CoalescedSceneObjects(UUID creatorId, params SceneObjectGroup[] objs) : this(creatorId)
101 {
102 foreach (SceneObjectGroup obj in objs)
103 Add(obj);
104 }
105
106 /// <summary>
107 /// Add an object to the coalescence.
108 /// </summary>
109 /// <param name="obj"></param>
110 /// <param name="offset">The offset of the object within the group</param>
111 public void Add(SceneObjectGroup obj)
112 {
113 lock (m_memberObjects)
114 m_memberObjects.Add(obj);
115 }
116
117 /// <summary>
118 /// Removes a scene object from the coalescene
119 /// </summary>
120 /// <param name="sceneObjectId"></param>
121 /// <returns>true if the object was there to be removed, false if not.</returns>
122 public bool Remove(SceneObjectGroup obj)
123 {
124 lock (m_memberObjects)
125 return m_memberObjects.Remove(obj);
126 }
127
128 /// <summary>
129 /// Get the total size of the coalescence (the size required to cover all the objects within it) and the
130 /// offsets of each of those objects.
131 /// </summary>
132 /// <param name="size"></param>
133 /// <returns>
134 /// An array of offsets. The order of objects is the same as returned from the Objects property
135 /// </returns>
136 public Vector3[] GetSizeAndOffsets(out Vector3 size)
137 {
138 float minX, minY, minZ;
139 float maxX, maxY, maxZ;
140
141 Vector3[] offsets
142 = Scene.GetCombinedBoundingBox(
143 Objects, out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
144
145 float sizeX = maxX - minX;
146 float sizeY = maxY - minY;
147 float sizeZ = maxZ - minZ;
148
149 size = new Vector3(sizeX, sizeY, sizeZ);
150
151 return offsets;
152 }
153 }
154} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index f9599f5..e3ed905 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -58,17 +58,8 @@ namespace OpenSim.Region.Framework.Scenes
58 58
59 public class Prioritizer 59 public class Prioritizer
60 { 60 {
61// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62 62
63 /// <summary>
64 /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the
65 /// viewer before child prim updates.
66 /// The adjustment is added to child prims and subtracted from root prims, so the gap ends up
67 /// being double. We do it both ways so that there is a still a priority delta even if the priority is already
68 /// double.MinValue or double.MaxValue.
69 /// </summary>
70 private double m_childPrimAdjustmentFactor = 0.05;
71
72 private Scene m_scene; 63 private Scene m_scene;
73 64
74 public Prioritizer(Scene scene) 65 public Prioritizer(Scene scene)
@@ -76,17 +67,35 @@ namespace OpenSim.Region.Framework.Scenes
76 m_scene = scene; 67 m_scene = scene;
77 } 68 }
78 69
79 public double GetUpdatePriority(IClientAPI client, ISceneEntity entity) 70 /// <summary>
71 /// Returns the priority queue into which the update should be placed. Updates within a
72 /// queue will be processed in arrival order. There are currently 12 priority queues
73 /// implemented in PriorityQueue class in LLClientView. Queue 0 is generally retained
74 /// for avatar updates. The fair queuing discipline for processing the priority queues
75 /// assumes that the number of entities in each priority queues increases exponentially.
76 /// So for example... if queue 1 contains all updates within 10m of the avatar or camera
77 /// then queue 2 at 20m is about 3X bigger in space & about 3X bigger in total number
78 /// of updates.
79 /// </summary>
80 public uint GetUpdatePriority(IClientAPI client, ISceneEntity entity)
80 { 81 {
81 double priority = 0; 82 // If entity is null we have a serious problem
82
83 if (entity == null) 83 if (entity == null)
84 return 100000; 84 {
85 m_log.WarnFormat("[PRIORITIZER] attempt to prioritize null entity");
86 throw new InvalidOperationException("Prioritization entity not defined");
87 }
88
89 // If this is an update for our own avatar give it the highest priority
90 if (client.AgentId == entity.UUID)
91 return 0;
92
93 uint priority;
85 94
86 switch (m_scene.UpdatePrioritizationScheme) 95 switch (m_scene.UpdatePrioritizationScheme)
87 { 96 {
88 case UpdatePrioritizationSchemes.Time: 97 case UpdatePrioritizationSchemes.Time:
89 priority = GetPriorityByTime(); 98 priority = GetPriorityByTime(client, entity);
90 break; 99 break;
91 case UpdatePrioritizationSchemes.Distance: 100 case UpdatePrioritizationSchemes.Distance:
92 priority = GetPriorityByDistance(client, entity); 101 priority = GetPriorityByDistance(client, entity);
@@ -104,180 +113,115 @@ namespace OpenSim.Region.Framework.Scenes
104 throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); 113 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
105 } 114 }
106 115
107 // Adjust priority so that root prims are sent to the viewer first. This is especially important for
108 // attachments acting as huds, since current viewers fail to display hud child prims if their updates
109 // arrive before the root one.
110 if (entity is SceneObjectPart)
111 {
112 SceneObjectPart sop = ((SceneObjectPart)entity);
113
114 if (sop.IsRoot)
115 {
116 if (priority >= double.MinValue + m_childPrimAdjustmentFactor)
117 priority -= m_childPrimAdjustmentFactor;
118 }
119 else
120 {
121 if (priority <= double.MaxValue - m_childPrimAdjustmentFactor)
122 priority += m_childPrimAdjustmentFactor;
123 }
124 }
125
126 return priority; 116 return priority;
127 } 117 }
128 118
129 private double GetPriorityByTime() 119
120 private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
130 { 121 {
131 return DateTime.UtcNow.ToOADate(); 122 return 1;
132 } 123 }
133 124
134 private double GetPriorityByDistance(IClientAPI client, ISceneEntity entity) 125 private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
135 { 126 {
136 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 127 return ComputeDistancePriority(client,entity,false);
137 if (presence != null) 128 }
138 { 129
139 // If this is an update for our own avatar give it the highest priority 130 private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
140 if (presence == entity) 131 {
141 return 0.0; 132 return ComputeDistancePriority(client,entity,true);
142
143 // Use the camera position for local agents and avatar position for remote agents
144 Vector3 presencePos = (presence.IsChildAgent) ?
145 presence.AbsolutePosition :
146 presence.CameraPosition;
147
148 // Use group position for child prims
149 Vector3 entityPos;
150 if (entity is SceneObjectPart)
151 {
152 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
153 // before its scheduled update was triggered
154 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
155 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
156 }
157 else
158 {
159 entityPos = entity.AbsolutePosition;
160 }
161
162 return Vector3.DistanceSquared(presencePos, entityPos);
163 }
164
165 return double.NaN;
166 } 133 }
167 134
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 135 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
169 { 136 {
137 uint pqueue = ComputeDistancePriority(client,entity,true);
138
170 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 139 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
171 if (presence != null) 140 if (presence != null)
172 { 141 {
173 // If this is an update for our own avatar give it the highest priority
174 if (presence == entity)
175 return 0.0;
176
177 // Use group position for child prims
178 Vector3 entityPos = entity.AbsolutePosition;
179 if (entity is SceneObjectPart)
180 {
181 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
182 // before its scheduled update was triggered
183 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
184 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
185 }
186 else
187 {
188 entityPos = entity.AbsolutePosition;
189 }
190
191 if (!presence.IsChildAgent) 142 if (!presence.IsChildAgent)
192 { 143 {
193 // Root agent. Use distance from camera and a priority decrease for objects behind us 144 if (entity is SceneObjectPart)
194 Vector3 camPosition = presence.CameraPosition; 145 {
195 Vector3 camAtAxis = presence.CameraAtAxis; 146 // Non physical prims are lower priority than physical prims
196 147 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
197 // Distance 148 if (physActor == null || !physActor.IsPhysical)
198 double priority = Vector3.DistanceSquared(camPosition, entityPos); 149 pqueue++;
199
200 // Plane equation
201 float d = -Vector3.Dot(camPosition, camAtAxis);
202 float p = Vector3.Dot(camAtAxis, entityPos) + d;
203 if (p < 0.0f) priority *= 2.0;
204
205 return priority;
206 }
207 else
208 {
209 // Child agent. Use the normal distance method
210 Vector3 presencePos = presence.AbsolutePosition;
211 150
212 return Vector3.DistanceSquared(presencePos, entityPos); 151 // Attachments are high priority,
152 // MIC: shouldn't these already be in the highest priority queue already
153 // since their root position is same as the avatars?
154 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
155 pqueue = 1;
156 }
213 } 157 }
214 } 158 }
215 159
216 return double.NaN; 160 return pqueue;
217 } 161 }
218 162
219 private double GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack)
220 { 164 {
221 // If this is an update for our own avatar give it the highest priority 165 // Get this agent's position
222 if (client.AgentId == entity.UUID) 166 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
223 return 0.0; 167 if (presence == null)
224 if (entity == null) 168 {
225 return double.NaN; 169 // this shouldn't happen, it basically means that we are prioritizing
170 // updates to send to a client that doesn't have a presence in the scene
171 // seems like there's race condition here...
226 172
227 // Use group position for child prims 173 // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
174 // throw new InvalidOperationException("Prioritization agent not defined");
175 return Int32.MaxValue;
176 }
177
178 // Use group position for child prims, since we are putting child prims in
179 // the same queue with the root of the group, the root prim (which goes into
180 // the queue first) should always be sent first, no need to adjust child prim
181 // priorities
228 Vector3 entityPos = entity.AbsolutePosition; 182 Vector3 entityPos = entity.AbsolutePosition;
229 if (entity is SceneObjectPart) 183 if (entity is SceneObjectPart)
230 { 184 {
231 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; 185 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup;
232 if (group != null) 186 if (group != null)
233 entityPos = group.AbsolutePosition; 187 entityPos = group.AbsolutePosition;
234 else
235 entityPos = entity.AbsolutePosition;
236 } 188 }
237 else
238 entityPos = entity.AbsolutePosition;
239 189
240 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 190 // Use the camera position for local agents and avatar position for remote agents
241 if (presence != null) 191 Vector3 presencePos = (presence.IsChildAgent) ?
242 { 192 presence.AbsolutePosition :
243 if (!presence.IsChildAgent) 193 presence.CameraPosition;
244 {
245 if (entity is ScenePresence)
246 return 1.0;
247
248 // Root agent. Use distance from camera and a priority decrease for objects behind us
249 Vector3 camPosition = presence.CameraPosition;
250 Vector3 camAtAxis = presence.CameraAtAxis;
251 194
252 // Distance 195 // Compute the distance...
253 double priority = Vector3.DistanceSquared(camPosition, entityPos); 196 double distance = Vector3.Distance(presencePos, entityPos);
254 197
255 // Plane equation 198 // And convert the distance to a priority queue, this computation gives queues
256 float d = -Vector3.Dot(camPosition, camAtAxis); 199 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
257 float p = Vector3.Dot(camAtAxis, entityPos) + d; 200 uint pqueue = 1;
258 if (p < 0.0f) priority *= 2.0; 201 for (int i = 0; i < 8; i++)
259 202 {
260 if (entity is SceneObjectPart) 203 if (distance < 10 * Math.Pow(2.0,i))
261 { 204 break;
262 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; 205 pqueue++;
263 if (physActor == null || !physActor.IsPhysical) 206 }
264 priority += 100; 207
265 208 // If this is a root agent, then determine front & back
266 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 209 // Bump up the priority queue (drop the priority) for any objects behind the avatar
267 priority = 1.0; 210 if (useFrontBack && ! presence.IsChildAgent)
268 } 211 {
269 return priority; 212 // Root agent, decrease priority for objects behind us
270 } 213 Vector3 camPosition = presence.CameraPosition;
271 else 214 Vector3 camAtAxis = presence.CameraAtAxis;
272 { 215
273 // Child agent. Use the normal distance method 216 // Plane equation
274 Vector3 presencePos = presence.AbsolutePosition; 217 float d = -Vector3.Dot(camPosition, camAtAxis);
275 218 float p = Vector3.Dot(camAtAxis, entityPos) + d;
276 return Vector3.DistanceSquared(presencePos, entityPos); 219 if (p < 0.0f)
277 } 220 pqueue++;
278 } 221 }
279 222
280 return double.NaN; 223 return pqueue;
281 } 224 }
225
282 } 226 }
283} 227}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 73dd531..0f85925 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1955,11 +1955,49 @@ namespace OpenSim.Region.Framework.Scenes
1955 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 1955 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
1956 bool RezSelected, bool RemoveItem, UUID fromTaskID) 1956 bool RezSelected, bool RemoveItem, UUID fromTaskID)
1957 { 1957 {
1958 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); 1958// m_log.DebugFormat(
1959 if (invAccess != null) 1959// "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}",
1960 invAccess.RezObject( 1960// remoteClient.Name, itemID, fromTaskID);
1961 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 1961
1962 RezSelected, RemoveItem, fromTaskID, false); 1962 if (fromTaskID == UUID.Zero)
1963 {
1964 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
1965 if (invAccess != null)
1966 invAccess.RezObject(
1967 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
1968 RezSelected, RemoveItem, fromTaskID, false);
1969 }
1970 else
1971 {
1972 SceneObjectPart part = GetSceneObjectPart(fromTaskID);
1973 if (part == null)
1974 {
1975 m_log.ErrorFormat(
1976 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object",
1977 remoteClient.Name, itemID, fromTaskID);
1978
1979 return;
1980 }
1981
1982 TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
1983 if (item == null)
1984 {
1985 m_log.ErrorFormat(
1986 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item",
1987 remoteClient.Name, itemID, fromTaskID);
1988
1989 return;
1990 }
1991
1992 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
1993 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
1994 Vector3 pos
1995 = GetNewRezLocation(
1996 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
1997 BypassRayCast, bRayEndIsIntersection, true, scale, false);
1998
1999 RezObject(part, item, pos, null, Vector3.Zero, 0);
2000 }
1963 } 2001 }
1964 2002
1965 /// <summary> 2003 /// <summary>
@@ -1967,14 +2005,14 @@ namespace OpenSim.Region.Framework.Scenes
1967 /// </summary> 2005 /// </summary>
1968 /// <param name="sourcePart"></param> 2006 /// <param name="sourcePart"></param>
1969 /// <param name="item"></param> 2007 /// <param name="item"></param>
1970 /// <param name="pos"></param> 2008 /// <param name="pos">The position of the rezzed object.</param>
1971 /// <param name="rot"></param> 2009 /// <param name="rot">The rotation of the rezzed object. If null, then the rotation stored with the object
1972 /// <param name="vel"></param> 2010 /// will be used if it exists.</param>
2011 /// <param name="vel">The velocity of the rezzed object.</param>
1973 /// <param name="param"></param> 2012 /// <param name="param"></param>
1974 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2013 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns>
1975 public virtual SceneObjectGroup RezObject( 2014 public virtual SceneObjectGroup RezObject(
1976 SceneObjectPart sourcePart, TaskInventoryItem item, 2015 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
1977 Vector3 pos, Quaternion rot, Vector3 vel, int param)
1978 { 2016 {
1979 if (null == item) 2017 if (null == item)
1980 return null; 2018 return null;
@@ -1992,8 +2030,14 @@ namespace OpenSim.Region.Framework.Scenes
1992 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 2030 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1993 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2031 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
1994 } 2032 }
1995 2033
1996 AddNewSceneObject(group, true, pos, rot, vel); 2034 AddNewSceneObject(group, true);
2035
2036 group.AbsolutePosition = pos;
2037 group.Velocity = vel;
2038
2039 if (rot != null)
2040 group.UpdateGroupRotationR((Quaternion)rot);
1997 2041
1998 // We can only call this after adding the scene object, since the scene object references the scene 2042 // We can only call this after adding the scene object, since the scene object references the scene
1999 // to find out if scripts should be activated at all. 2043 // to find out if scripts should be activated at all.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f0acc38..01de824 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3665,6 +3665,15 @@ namespace OpenSim.Region.Framework.Scenes
3665 return false; 3665 return false;
3666 } 3666 }
3667 3667
3668 int num = m_sceneGraph.GetNumberOfScenePresences();
3669
3670 if (num >= RegionInfo.RegionSettings.AgentLimit)
3671 {
3672 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3673 return false;
3674 }
3675
3676
3668 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3677 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3669 3678
3670 if (childAgentUpdate != null) 3679 if (childAgentUpdate != null)
@@ -4839,7 +4848,20 @@ namespace OpenSim.Region.Framework.Scenes
4839 } 4848 }
4840 } 4849 }
4841 4850
4842 public Vector3[] GetCombinedBoundingBox(List<SceneObjectGroup> objects, out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 4851 /// <summary>
4852 /// Get the volume of space that will encompass all the given objects.
4853 /// </summary>
4854 /// <param name="objects"></param>
4855 /// <param name="minX"></param>
4856 /// <param name="maxX"></param>
4857 /// <param name="minY"></param>
4858 /// <param name="maxY"></param>
4859 /// <param name="minZ"></param>
4860 /// <param name="maxZ"></param>
4861 /// <returns></returns>
4862 public static Vector3[] GetCombinedBoundingBox(
4863 List<SceneObjectGroup> objects,
4864 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
4843 { 4865 {
4844 minX = 256; 4866 minX = 256;
4845 maxX = -256; 4867 maxX = -256;
@@ -4857,6 +4879,10 @@ namespace OpenSim.Region.Framework.Scenes
4857 Vector3 vec = g.AbsolutePosition; 4879 Vector3 vec = g.AbsolutePosition;
4858 4880
4859 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 4881 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4882
4883// m_log.DebugFormat(
4884// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
4885// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
4860 4886
4861 ominX += vec.X; 4887 ominX += vec.X;
4862 omaxX += vec.X; 4888 omaxX += vec.X;
@@ -4949,6 +4975,17 @@ namespace OpenSim.Region.Framework.Scenes
4949 // child agent creation, thereby emulating the SL behavior. 4975 // child agent creation, thereby emulating the SL behavior.
4950 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 4976 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4951 { 4977 {
4978 int num = m_sceneGraph.GetNumberOfScenePresences();
4979
4980 if (num >= RegionInfo.RegionSettings.AgentLimit)
4981 {
4982 if (!Permissions.IsAdministrator(agentID))
4983 {
4984 reason = "The region is full";
4985 return false;
4986 }
4987 }
4988
4952 reason = String.Empty; 4989 reason = String.Empty;
4953 return true; 4990 return true;
4954 } 4991 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 97af0a0..fc31b65 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes
800 return m_scenePresenceArray; 800 return m_scenePresenceArray;
801 } 801 }
802 802
803 public int GetNumberOfScenePresences()
804 {
805 return m_scenePresenceArray.Count;
806 }
807
803 /// <summary> 808 /// <summary>
804 /// Request a scene presence by UUID. Fast, indexed lookup. 809 /// Request a scene presence by UUID. Fast, indexed lookup.
805 /// </summary> 810 /// </summary>
@@ -997,6 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes
997 { 1002 {
998 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) 1003 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
999 { 1004 {
1005// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name);
1006
1000 if (p.Name == name) 1007 if (p.Name == name)
1001 { 1008 {
1002 sop = p; 1009 sop = p;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index e8095c0..4bca3d0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes
81 } 81 }
82 82
83 /// <summary> 83 /// <summary>
84 /// Add an inventory item to a prim in this group. 84 /// Add an inventory item from a user's inventory to a prim in this scene object.
85 /// </summary> 85 /// </summary>
86 /// <param name="remoteClient"></param> 86 /// <param name="remoteClient">The client adding the item.</param>
87 /// <param name="localID"></param> 87 /// <param name="localID">The local ID of the part receiving the add.</param>
88 /// <param name="item"></param> 88 /// <param name="item">The user inventory item being added.</param>
89 /// <param name="copyItemID">The item UUID that should be used by the new item.</param> 89 /// <param name="copyItemID">The item UUID that should be used by the new item.</param>
90 /// <returns></returns> 90 /// <returns></returns>
91 public bool AddInventoryItem(IClientAPI remoteClient, uint localID, 91 public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
92 InventoryItemBase item, UUID copyItemID) 92 InventoryItemBase item, UUID copyItemID)
93 { 93 {
94// m_log.DebugFormat(
95// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",
96// item.Name, remoteClient.Name, localID);
97
94 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; 98 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
95 99
96 SceneObjectPart part = GetChildPart(localID); 100 SceneObjectPart part = GetChildPart(localID);
@@ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes
132 taskItem.GroupPermissions = item.GroupPermissions; 136 taskItem.GroupPermissions = item.GroupPermissions;
133 taskItem.NextPermissions = item.NextPermissions; 137 taskItem.NextPermissions = item.NextPermissions;
134 } 138 }
135 139
136 taskItem.Flags = item.Flags; 140 taskItem.Flags = item.Flags;
141
142// m_log.DebugFormat(
143// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
144// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
145
137 // TODO: These are pending addition of those fields to TaskInventoryItem 146 // TODO: These are pending addition of those fields to TaskInventoryItem
138// taskItem.SalePrice = item.SalePrice; 147// taskItem.SalePrice = item.SalePrice;
139// taskItem.SaleType = item.SaleType; 148// taskItem.SaleType = item.SaleType;
140 taskItem.CreationDate = (uint)item.CreationDate; 149 taskItem.CreationDate = (uint)item.CreationDate;
141 150
142 bool addFromAllowedDrop = false; 151 bool addFromAllowedDrop = false;
143 if (remoteClient!=null) 152 if (remoteClient != null)
144 { 153 {
145 addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; 154 addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
146 } 155 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index ca7d9d9..19a9506 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -296,11 +296,14 @@ namespace OpenSim.Region.Framework.Scenes
296 { 296 {
297 Vector3 val = value; 297 Vector3 val = value;
298 298
299 if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 299 if (Scene != null)
300 || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
301 && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims))
302 { 300 {
303 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 301 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
302 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
303 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
304 {
305 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
306 }
304 } 307 }
305 308
306 if (RootPart.GetStatusSandbox()) 309 if (RootPart.GetStatusSandbox())
@@ -308,8 +311,11 @@ namespace OpenSim.Region.Framework.Scenes
308 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 311 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
309 { 312 {
310 RootPart.ScriptSetPhysicsStatus(false); 313 RootPart.ScriptSetPhysicsStatus(false);
311 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 314
312 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 315 if (Scene != null)
316 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
317 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
318
313 return; 319 return;
314 } 320 }
315 } 321 }
@@ -326,7 +332,8 @@ namespace OpenSim.Region.Framework.Scenes
326 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 332 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
327 //} 333 //}
328 334
329 m_scene.EventManager.TriggerParcelPrimCountTainted(); 335 if (Scene != null)
336 Scene.EventManager.TriggerParcelPrimCountTainted();
330 } 337 }
331 } 338 }
332 339
@@ -1765,10 +1772,12 @@ namespace OpenSim.Region.Framework.Scenes
1765 /// <param name="part"></param> 1772 /// <param name="part"></param>
1766 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 1773 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
1767 { 1774 {
1768 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, 1775 remoteClient.SendObjectPropertiesFamilyData(RootPart, RequestFlags);
1769 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 1776
1770 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 1777// remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
1771 RootPart.CreatorID, RootPart.Name, RootPart.Description); 1778// RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
1779// RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
1780// RootPart.CreatorID, RootPart.Name, RootPart.Description);
1772 } 1781 }
1773 1782
1774 public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID) 1783 public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4d5eedf..8a8a699 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2055,15 +2055,7 @@ namespace OpenSim.Region.Framework.Scenes
2055 2055
2056 public void GetProperties(IClientAPI client) 2056 public void GetProperties(IClientAPI client)
2057 { 2057 {
2058 //Viewer wants date in microseconds so multiply it by 1,000,000. 2058 client.SendObjectPropertiesReply(this);
2059 client.SendObjectPropertiesReply(
2060 m_fromUserInventoryItemID, (ulong)_creationDate*(ulong)1e6, _creatorID, UUID.Zero, UUID.Zero,
2061 _groupID, (short)InventorySerial, _lastOwnerID, UUID, _ownerID,
2062 ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description,
2063 ParentGroup.RootPart._ownerMask, ParentGroup.RootPart._nextOwnerMask, ParentGroup.RootPart._groupMask, ParentGroup.RootPart._everyoneMask,
2064 ParentGroup.RootPart._baseMask,
2065 ParentGroup.RootPart.ObjectSaleType,
2066 ParentGroup.RootPart.SalePrice);
2067 } 2059 }
2068 2060
2069 public UUID GetRootPartUUID() 2061 public UUID GetRootPartUUID()
@@ -2088,7 +2080,14 @@ namespace OpenSim.Region.Framework.Scenes
2088 2080
2089 axPos *= parentRot; 2081 axPos *= parentRot;
2090 Vector3 translationOffsetPosition = axPos; 2082 Vector3 translationOffsetPosition = axPos;
2091 return GroupPosition + translationOffsetPosition; 2083
2084// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name);
2085
2086 Vector3 worldPos = GroupPosition + translationOffsetPosition;
2087
2088// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name);
2089
2090 return worldPos;
2092 } 2091 }
2093 2092
2094 /// <summary> 2093 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
new file mode 100644
index 0000000..55455cc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
@@ -0,0 +1,160 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.IO;
32using System.Reflection;
33using System.Xml;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39
40namespace OpenSim.Region.Framework.Scenes.Serialization
41{
42 /// <summary>
43 /// Serialize and deserialize coalesced scene objects.
44 /// </summary>
45 /// <remarks>
46 /// Deserialization not yet here.
47 /// </remarks>
48 public class CoalescedSceneObjectsSerializer
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 /// <summary>
53 /// Serialize coalesced objects to Xml
54 /// </summary>
55 /// <param name="coa"></param>
56 /// <returns></returns>
57 public static string ToXml(CoalescedSceneObjects coa)
58 {
59 using (StringWriter sw = new StringWriter())
60 {
61 using (XmlTextWriter writer = new XmlTextWriter(sw))
62 {
63 Vector3 size;
64
65 List<SceneObjectGroup> coaObjects = coa.Objects;
66
67// m_log.DebugFormat(
68// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object",
69// coaObjects.Count);
70
71 // This is weak - we're relying on the set of coalesced objects still being identical
72 Vector3[] offsets = coa.GetSizeAndOffsets(out size);
73
74 writer.WriteStartElement("CoalescedObject");
75
76 writer.WriteAttributeString("x", size.X.ToString());
77 writer.WriteAttributeString("y", size.Y.ToString());
78 writer.WriteAttributeString("z", size.Z.ToString());
79
80 // Embed the offsets into the group XML
81 for (int i = 0; i < coaObjects.Count; i++)
82 {
83 SceneObjectGroup obj = coaObjects[i];
84
85// m_log.DebugFormat(
86// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing offset for object {0}, {1}",
87// i, obj.Name);
88
89 writer.WriteStartElement("SceneObjectGroup");
90 writer.WriteAttributeString("offsetx", offsets[i].X.ToString());
91 writer.WriteAttributeString("offsety", offsets[i].Y.ToString());
92 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString());
93
94 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true);
95
96 writer.WriteEndElement(); // SceneObjectGroup
97 }
98
99 writer.WriteEndElement(); // CoalescedObject
100 }
101
102 string output = sw.ToString();
103
104// Console.WriteLine(output);
105
106 return output;
107 }
108 }
109
110 public static bool TryFromXml(string xml, out CoalescedSceneObjects coa)
111 {
112// m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml);
113
114 coa = null;
115
116 using (StringReader sr = new StringReader(xml))
117 {
118 using (XmlTextReader reader = new XmlTextReader(sr))
119 {
120 try
121 {
122 reader.Read();
123 if (reader.Name != "CoalescedObject")
124 {
125 // m_log.DebugFormat(
126 // "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
127 // reader.Name);
128
129 return false;
130 }
131
132 coa = new CoalescedSceneObjects(UUID.Zero);
133 reader.Read();
134
135 while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
136 {
137 if (reader.Name == "SceneObjectGroup")
138 {
139 string soXml = reader.ReadOuterXml();
140 coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
141 }
142 }
143
144 reader.ReadEndElement(); // CoalescedObject
145 }
146 catch (Exception e)
147 {
148 m_log.ErrorFormat(
149 "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}",
150 e.Message, e.StackTrace);
151
152 return false;
153 }
154 }
155 }
156
157 return true;
158 }
159 }
160} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 57ae4fd..bb8a83a 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -139,6 +139,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
139 return sw.ToString(); 139 return sw.ToString();
140 } 140 }
141 } 141 }
142
142 143
143 /// <summary> 144 /// <summary>
144 /// Serialize a scene object to the original xml format 145 /// Serialize a scene object to the original xml format
@@ -147,10 +148,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
147 /// <returns></returns> 148 /// <returns></returns>
148 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer) 149 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer)
149 { 150 {
151 ToOriginalXmlFormat(sceneObject, writer, false);
152 }
153
154 /// <summary>
155 /// Serialize a scene object to the original xml format
156 /// </summary>
157 /// <param name="sceneObject"></param>
158 /// <param name="writer"></param>
159 /// <param name="noRootElement">If false, don't write the enclosing SceneObjectGroup element</param>
160 /// <returns></returns>
161 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer, bool noRootElement)
162 {
150 //m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name); 163 //m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name);
151 //int time = System.Environment.TickCount; 164 //int time = System.Environment.TickCount;
152 165
153 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); 166 if (!noRootElement)
167 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
168
154 writer.WriteStartElement(String.Empty, "RootPart", String.Empty); 169 writer.WriteStartElement(String.Empty, "RootPart", String.Empty);
155 ToXmlFormat(sceneObject.RootPart, writer); 170 ToXmlFormat(sceneObject.RootPart, writer);
156 writer.WriteEndElement(); 171 writer.WriteEndElement();
@@ -170,10 +185,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
170 185
171 writer.WriteEndElement(); // OtherParts 186 writer.WriteEndElement(); // OtherParts
172 sceneObject.SaveScriptedState(writer); 187 sceneObject.SaveScriptedState(writer);
173 writer.WriteEndElement(); // SceneObjectGroup 188
189 if (!noRootElement)
190 writer.WriteEndElement(); // SceneObjectGroup
174 191
175 //m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); 192 //m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
176 } 193 }
177 194
178 protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer) 195 protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer)
179 { 196 {
@@ -1318,7 +1335,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1318 writer.WriteStartElement("SculptData"); 1335 writer.WriteStartElement("SculptData");
1319 byte[] sd; 1336 byte[] sd;
1320 if (shp.SculptData != null) 1337 if (shp.SculptData != null)
1321 sd = shp.ExtraParams; 1338 sd = shp.SculptData;
1322 else 1339 else
1323 sd = Utils.EmptyBytes; 1340 sd = Utils.EmptyBytes;
1324 writer.WriteBase64(sd, 0, sd.Length); 1341 writer.WriteBase64(sd, 0, sd.Length);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
index 8588f7f..dd28416 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
@@ -117,11 +117,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
117 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 117 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
118 118
119 119
120 Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010, "grid"); 120 Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010);
121 SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms); 121 SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms);
122 sceneB.RegisterRegionWithGrid(); 122 sceneB.RegisterRegionWithGrid();
123 123
124 Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000, "grid"); 124 Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000);
125 SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms); 125 SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms);
126 sceneA.RegisterRegionWithGrid(); 126 sceneA.RegisterRegionWithGrid();
127 127
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index 8138bcc..2aef4b0 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.Framework.Tests
101 TestHelper.InMethod(); 101 TestHelper.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 102// log4net.Config.XmlConfigurator.Configure();
103 103
104 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 104 Scene scene = SceneSetupHelpers.SetupScene();
105 UserAccount user1 = CreateUser(scene); 105 UserAccount user1 = CreateUser(scene);
106 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); 106 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
107 SceneObjectPart sop1 = sog1.RootPart; 107 SceneObjectPart sop1 = sog1.RootPart;
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Tests
127 TestHelper.InMethod(); 127 TestHelper.InMethod();
128// log4net.Config.XmlConfigurator.Configure(); 128// log4net.Config.XmlConfigurator.Configure();
129 129
130 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 130 Scene scene = SceneSetupHelpers.SetupScene();
131 UserAccount user1 = CreateUser(scene); 131 UserAccount user1 = CreateUser(scene);
132 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); 132 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
133 SceneObjectPart sop1 = sog1.RootPart; 133 SceneObjectPart sop1 = sog1.RootPart;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 6b70865..dbf9e0f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -47,7 +47,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
47 [SetUp] 47 [SetUp]
48 public void Init() 48 public void Init()
49 { 49 {
50 m_assetService = new MockAssetService(); 50 // FIXME: We don't need a full scene here - it would be enough to set up the asset service.
51 Scene scene = SceneSetupHelpers.SetupScene();
52 m_assetService = scene.AssetService;
51 m_uuidGatherer = new UuidGatherer(m_assetService); 53 m_uuidGatherer = new UuidGatherer(m_assetService);
52 } 54 }
53 55
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 83906d7..77b1535 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes
298 if (null != objectAsset) 298 if (null != objectAsset)
299 { 299 {
300 string xml = Utils.BytesToString(objectAsset.Data); 300 string xml = Utils.BytesToString(objectAsset.Data);
301 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); 301
302 302 CoalescedSceneObjects coa;
303 if (null != sog) 303 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
304 GatherAssetUuids(sog, assetUuids); 304 {
305 foreach (SceneObjectGroup sog in coa.Objects)
306 GatherAssetUuids(sog, assetUuids);
307 }
308 else
309 {
310 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
311
312 if (null != sog)
313 GatherAssetUuids(sog, assetUuids);
314 }
305 } 315 }
306 } 316 }
307 317
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 821cd4b..4b6e52e 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1332,14 +1332,13 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1332 1332
1333 } 1333 }
1334 1334
1335 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, UUID LastOwnerID, string ObjectName, string Description) 1335 public void SendObjectPropertiesFamilyData(ISceneEntity Entity, uint RequestFlags)
1336 { 1336 {
1337 1337
1338 } 1338 }
1339 1339
1340 public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, uint BaseMask, byte saleType, int salePrice) 1340 public void SendObjectPropertiesReply(ISceneEntity entity)
1341 { 1341 {
1342
1343 } 1342 }
1344 1343
1345 public void SendAgentOffline(UUID[] agentIDs) 1344 public void SendAgentOffline(UUID[] agentIDs)
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 7909d8a..42efd67 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
118 118
119 if (serviceDll == String.Empty) 119 if (serviceDll == String.Empty)
120 { 120 {
121 m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice"); 121 m_log.Error("[FreeSwitchVoice]: No LocalServiceModule named in section FreeSwitchVoice. Not starting.");
122 return; 122 return;
123 } 123 }
124 124
@@ -143,8 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
143 if (String.IsNullOrEmpty(m_freeSwitchRealm) || 143 if (String.IsNullOrEmpty(m_freeSwitchRealm) ||
144 String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) 144 String.IsNullOrEmpty(m_freeSwitchAPIPrefix))
145 { 145 {
146 m_log.Error("[FreeSwitchVoice] plugin mis-configured"); 146 m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured. Not starting.");
147 m_log.Info("[FreeSwitchVoice] plugin disabled: incomplete configuration");
148 return; 147 return;
149 } 148 }
150 149
@@ -164,24 +163,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
164 // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler); 163 // String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceGetPreloginHTTPHandler);
165 // MainServer.Instance.AddStreamHandler(h); 164 // MainServer.Instance.AddStreamHandler(h);
166 165
167
168
169 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix), 166 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix),
170 FreeSwitchSLVoiceSigninHTTPHandler); 167 FreeSwitchSLVoiceSigninHTTPHandler);
171 168
172 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), 169 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix),
173 FreeSwitchSLVoiceBuddyHTTPHandler); 170 FreeSwitchSLVoiceBuddyHTTPHandler);
171
172 MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_watcher.php", m_freeSwitchAPIPrefix),
173 FreeSwitchSLVoiceWatcherHTTPHandler);
174 174
175 m_log.InfoFormat("[FreeSwitchVoice] using FreeSwitch server {0}", m_freeSwitchRealm); 175 m_log.InfoFormat("[FreeSwitchVoice]: using FreeSwitch server {0}", m_freeSwitchRealm);
176 176
177 m_Enabled = true; 177 m_Enabled = true;
178 178
179 m_log.Info("[FreeSwitchVoice] plugin enabled"); 179 m_log.Info("[FreeSwitchVoice]: plugin enabled");
180 } 180 }
181 catch (Exception e) 181 catch (Exception e)
182 { 182 {
183 m_log.ErrorFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.Message); 183 m_log.ErrorFormat("[FreeSwitchVoice]: plugin initialization failed: {0} {1}", e.Message, e.StackTrace);
184 m_log.DebugFormat("[FreeSwitchVoice] plugin initialization failed: {0}", e.ToString());
185 return; 184 return;
186 } 185 }
187 186
@@ -240,7 +239,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
240 { 239 {
241 if (m_Enabled) 240 if (m_Enabled)
242 { 241 {
243 m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); 242 m_log.Info("[FreeSwitchVoice]: registering IVoiceModule with the scene");
244 243
245 // register the voice interface for this module, so the script engine can call us 244 // register the voice interface for this module, so the script engine can call us
246 scene.RegisterModuleInterface<IVoiceModule>(this); 245 scene.RegisterModuleInterface<IVoiceModule>(this);
@@ -302,7 +301,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
302 // </summary> 301 // </summary>
303 public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) 302 public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps)
304 { 303 {
305 m_log.DebugFormat("[FreeSwitchVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 304 m_log.DebugFormat(
305 "[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}",
306 agentID, caps, scene.RegionInfo.RegionName);
306 307
307 string capsBase = "/CAPS/" + caps.CapsObjectPath; 308 string capsBase = "/CAPS/" + caps.CapsObjectPath;
308 caps.RegisterHandler("ProvisionVoiceAccountRequest", 309 caps.RegisterHandler("ProvisionVoiceAccountRequest",
@@ -344,6 +345,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
344 public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param, 345 public string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param,
345 UUID agentID, Caps caps) 346 UUID agentID, Caps caps)
346 { 347 {
348 m_log.DebugFormat(
349 "[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request: {0}, path: {1}, param: {2}", request, path, param);
350
347 ScenePresence avatar = scene.GetScenePresence(agentID); 351 ScenePresence avatar = scene.GetScenePresence(agentID);
348 if (avatar == null) 352 if (avatar == null)
349 { 353 {
@@ -357,9 +361,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
357 361
358 try 362 try
359 { 363 {
360 //m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
361 // request, path, param);
362
363 //XmlElement resp; 364 //XmlElement resp;
364 string agentname = "x" + Convert.ToBase64String(agentID.GetBytes()); 365 string agentname = "x" + Convert.ToBase64String(agentID.GetBytes());
365 string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16); 366 string password = "1234";//temp hack//new UUID(Guid.NewGuid()).ToString().Replace('-','Z').Substring(0,16);
@@ -390,7 +391,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
390 391
391 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); 392 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
392 393
393 m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); 394// m_log.DebugFormat("[FreeSwitchVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
394 395
395 return r; 396 return r;
396 } 397 }
@@ -416,6 +417,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
416 public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, 417 public string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param,
417 UUID agentID, Caps caps) 418 UUID agentID, Caps caps)
418 { 419 {
420// m_log.DebugFormat(
421// "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}",
422// scene.RegionInfo.RegionName, agentID);
423
419 ScenePresence avatar = scene.GetScenePresence(agentID); 424 ScenePresence avatar = scene.GetScenePresence(agentID);
420 string avatarName = avatar.Name; 425 string avatarName = avatar.Name;
421 426
@@ -453,8 +458,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
453 458
454 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) 459 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
455 { 460 {
456 m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", 461// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel",
457 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); 462// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName);
458 channelUri = String.Empty; 463 channelUri = String.Empty;
459 } 464 }
460 else 465 else
@@ -469,8 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
469 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); 474 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
470 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); 475 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
471 476
472 m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", 477// m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
473 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); 478// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
474 return r; 479 return r;
475 } 480 }
476 catch (Exception e) 481 catch (Exception e)
@@ -502,6 +507,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
502 507
503 m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", 508 m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
504 avatarName, request, path, param); 509 avatarName, request, path, param);
510
505 return "<llsd>true</llsd>"; 511 return "<llsd>true</llsd>";
506 } 512 }
507 513
@@ -555,10 +561,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
555 return response; 561 return response;
556 } 562 }
557 563
558
559 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) 564 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
560 { 565 {
561 m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called"); 566 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called");
562 567
563 Hashtable response = new Hashtable(); 568 Hashtable response = new Hashtable();
564 response["content_type"] = "text/xml"; 569 response["content_type"] = "text/xml";
@@ -592,6 +597,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
592 597
593 public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request) 598 public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request)
594 { 599 {
600 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceBuddyHTTPHandler called");
601
595 Hashtable response = new Hashtable(); 602 Hashtable response = new Hashtable();
596 response["int_response_code"] = 200; 603 response["int_response_code"] = 200;
597 response["str_response_string"] = string.Empty; 604 response["str_response_string"] = string.Empty;
@@ -650,21 +657,64 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
650 <bdy_status>A</bdy_status> 657 <bdy_status>A</bdy_status>
651 <modified_ts>{3}</modified_ts> 658 <modified_ts>{3}</modified_ts>
652 <b2g_group_id></b2g_group_id> 659 <b2g_group_id></b2g_group_id>
653 </level3>", ids[i],i,m_freeSwitchRealm,dt)); 660 </level3>", ids[i], i ,m_freeSwitchRealm, dt));
654 } 661 }
655 662
656 resp.Append("</buddies><groups></groups></body></level0></response>"); 663 resp.Append("</buddies><groups></groups></body></level0></response>");
657 664
658 response["str_response_string"] = resp.ToString(); 665 response["str_response_string"] = resp.ToString();
659// Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); 666// Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
660 667//
661 //m_log.DebugFormat("[FREESWITCH]: {0}", normalizeEndLines.Replace((string)response["str_response_string"],"")); 668// m_log.DebugFormat(
669// "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}",
670// normalizeEndLines.Replace((string)response["str_response_string"],""));
671
662 return response; 672 return response;
663 } 673 }
664 674
675 public Hashtable FreeSwitchSLVoiceWatcherHTTPHandler(Hashtable request)
676 {
677 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceWatcherHTTPHandler called");
678
679 Hashtable response = new Hashtable();
680 response["int_response_code"] = 200;
681 response["content-type"] = "text/xml";
682
683 Hashtable requestBody = ParseRequestBody((string)request["body"]);
684
685 string auth_token = (string)requestBody["auth_token"];
686 //string[] auth_tokenvals = auth_token.Split(':');
687 //string username = auth_tokenvals[0];
688
689 StringBuilder resp = new StringBuilder();
690 resp.Append("<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?><response xmlns=\"http://www.vivox.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation= \"/xsd/buddy_list.xsd\">");
691
692 // FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work. If we don't
693 // give an OK response, then viewer 2 engages in an continuous viv_signin.php, viv_buddy.php, viv_watcher.php loop
694 // Viewer 1 appeared happy to ignore the lack of reply and still works with this reply.
695 //
696 // However, really we need to fill in whatever watcher data should be here (whatever that is).
697 resp.Append(string.Format(@"<level0>
698 <status>OK</status>
699 <cookie_name>lib_session</cookie_name>
700 <cookie>{0}</cookie>
701 <auth_token>{0}</auth_token>
702 <body/></level0></response>", auth_token));
703
704 response["str_response_string"] = resp.ToString();
705
706// Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
707//
708// m_log.DebugFormat(
709// "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}",
710// normalizeEndLines.Replace((string)response["str_response_string"],""));
711
712 return response;
713 }
714
665 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) 715 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
666 { 716 {
667 m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called"); 717 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called");
668// string requestbody = (string)request["body"]; 718// string requestbody = (string)request["body"];
669// string uri = (string)request["uri"]; 719// string uri = (string)request["uri"];
670// string contenttype = (string)request["content-type"]; 720// string contenttype = (string)request["content-type"];
@@ -709,7 +759,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
709 </level0> 759 </level0>
710 </response>", userid, pos, avatarName); 760 </response>", userid, pos, avatarName);
711 761
712 response["int_response_code"] = 200; 762 response["int_response_code"] = 200;
763
764// m_log.DebugFormat("[FreeSwitchVoice]: Sending FreeSwitchSLVoiceSigninHTTPHandler response");
765
713 return response; 766 return response;
714 } 767 }
715 768
@@ -795,16 +848,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
795 response["keepalive"] = false; 848 response["keepalive"] = false;
796 response["int_response_code"] = 500; 849 response["int_response_code"] = 500;
797 850
798 Hashtable requestBody = ParseRequestBody((string) request["body"]); 851 Hashtable requestBody = ParseRequestBody((string)request["body"]);
799 852
800 string section = (string) requestBody["section"]; 853 string section = (string) requestBody["section"];
801 854
802 if (section == "directory") 855 if (section == "directory")
856 {
857 string eventCallingFunction = (string)requestBody["Event-Calling-Function"];
858 m_log.DebugFormat(
859 "[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'",
860 eventCallingFunction);
861
803 response = m_FreeswitchService.HandleDirectoryRequest(requestBody); 862 response = m_FreeswitchService.HandleDirectoryRequest(requestBody);
863 }
804 else if (section == "dialplan") 864 else if (section == "dialplan")
865 {
866 m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan");
867
805 response = m_FreeswitchService.HandleDialplanRequest(requestBody); 868 response = m_FreeswitchService.HandleDialplanRequest(requestBody);
869 }
806 else 870 else
807 m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section); 871 m_log.WarnFormat("[FreeSwitchVoice]: Unknown section {0} was requested from config.", section);
808 872
809 return response; 873 return response;
810 } 874 }
@@ -821,4 +885,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
821 885
822 #endregion 886 #endregion
823 } 887 }
824} 888} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 96760a2..2504e30 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -786,18 +786,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
786 { 786 {
787 } 787 }
788 788
789 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, 789 public void SendObjectPropertiesFamilyData(ISceneEntity Entity, uint RequestFlags)
790 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
791 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category,
792 UUID LastOwnerID, string ObjectName, string Description)
793 { 790 {
791
794 } 792 }
795 793
796 public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, 794 public void SendObjectPropertiesReply(ISceneEntity entity)
797 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
798 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
799 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
800 uint BaseMask, byte saleType, int salePrice)
801 { 795 {
802 } 796 }
803 797
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
index 85e34c1..6df213d 100644
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
@@ -648,6 +648,9 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin
648 if (pbs.ProfileHollow != 0) 648 if (pbs.ProfileHollow != 0)
649 iPropertiesNotSupportedDefault++; 649 iPropertiesNotSupportedDefault++;
650 650
651 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
652 iPropertiesNotSupportedDefault++;
653
651 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) 654 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
652 iPropertiesNotSupportedDefault++; 655 iPropertiesNotSupportedDefault++;
653 656
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 211a0a7..64774d8 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -84,10 +84,11 @@ namespace OpenSim.Region.Physics.Meshing
84 public Meshmerizer(IConfigSource config) 84 public Meshmerizer(IConfigSource config)
85 { 85 {
86 IConfig start_config = config.Configs["Startup"]; 86 IConfig start_config = config.Configs["Startup"];
87 IConfig mesh_config = config.Configs["Mesh"];
87 88
88 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); 89 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
89 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); 90 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
90 useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); 91 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
91 92
92 try 93 try
93 { 94 {
diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs
index d2d71de..740424e 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMap.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMap.cs
@@ -62,6 +62,8 @@ namespace PrimMesher
62 62
63 bool needsScaling = false; 63 bool needsScaling = false;
64 64
65 bool smallMap = bmW * bmH <= lod * lod;
66
65 width = bmW; 67 width = bmW;
66 height = bmH; 68 height = bmH;
67 while (width * height > numLodPixels) 69 while (width * height > numLodPixels)
@@ -104,9 +106,14 @@ namespace PrimMesher
104 { 106 {
105 for (int x = 0; x <= width; x++) 107 for (int x = 0; x <= width; x++)
106 { 108 {
107 int bmY = y < height ? y * 2 : y * 2 - 1; 109 Color c;
108 int bmX = x < width ? x * 2 : x * 2 - 1; 110
109 Color c = bm.GetPixel(bmX, bmY); 111 if (smallMap)
112 c = bm.GetPixel(x < width ? x : x - 1,
113 y < height ? y : y - 1);
114 else
115 c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1,
116 y < height ? y * 2 : y * 2 - 1);
110 117
111 redBytes[byteNdx] = c.R; 118 redBytes[byteNdx] = c.R;
112 greenBytes[byteNdx] = c.G; 119 greenBytes[byteNdx] = c.G;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index eb97f41..a0101af 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -2528,6 +2528,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2528 if (pbs.ProfileHollow != 0) 2528 if (pbs.ProfileHollow != 0)
2529 iPropertiesNotSupportedDefault++; 2529 iPropertiesNotSupportedDefault++;
2530 2530
2531 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
2532 iPropertiesNotSupportedDefault++;
2533
2531 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) 2534 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
2532 iPropertiesNotSupportedDefault++; 2535 iPropertiesNotSupportedDefault++;
2533 2536
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index c16a985..aa28fa0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -10289,12 +10289,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10289 { 10289 {
10290 UUID rq = UUID.Random(); 10290 UUID rq = UUID.Random();
10291 10291
10292 UUID tid = AsyncCommands. 10292 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
10293 DataserverPlugin.RegisterRequest(m_localID,
10294 m_itemID, rq.ToString());
10295 10293
10296 AsyncCommands. 10294 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
10297 DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
10298 10295
10299 return rq.ToString(); 10296 return rq.ToString();
10300 } 10297 }
@@ -10308,12 +10305,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10308 { 10305 {
10309 UUID rq = UUID.Random(); 10306 UUID rq = UUID.Random();
10310 10307
10311 UUID tid = AsyncCommands. 10308 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
10312 DataserverPlugin.RegisterRequest(m_localID,
10313 m_itemID, rq.ToString());
10314 10309
10315 AsyncCommands. 10310 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
10316 DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
10317 10311
10318 return rq.ToString(); 10312 return rq.ToString();
10319 } 10313 }