From d52b2b9ee7c189651f9d7c04ddf3df9aa833b7ff Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 16 Sep 2010 20:46:24 +0100 Subject: [PATCH 1/8] minor: remove some mono compiler warnings --- OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs index b47ad5dcb1..fc44358b69 100644 --- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs @@ -84,7 +84,7 @@ namespace OpenSim.Tests.Common.Mock public List getInventoryInFolder(UUID folderID) { - InventoryFolderBase folder = m_folders[folderID]; +// InventoryFolderBase folder = m_folders[folderID]; // m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0} {1}", folder.Name, folder.ID); @@ -116,7 +116,7 @@ namespace OpenSim.Tests.Common.Mock public List getInventoryFolders(UUID parentID) { - InventoryFolderBase parentFolder = m_folders[parentID]; +// InventoryFolderBase parentFolder = m_folders[parentID]; // m_log.DebugFormat("[MOCK INV DB]: Getting folders in folder {0} {1}", parentFolder.Name, parentFolder.ID); @@ -185,7 +185,7 @@ namespace OpenSim.Tests.Common.Mock public void addInventoryItem(InventoryItemBase item) { - InventoryFolderBase folder = m_folders[item.Folder]; +// InventoryFolderBase folder = m_folders[item.Folder]; // m_log.DebugFormat( // "[MOCK INV DB]: Adding inventory item {0} {1} in {2} {3}", item.Name, item.ID, folder.Name, folder.ID); From 1b2edfe75f4fe8b320f65ad54f6f2b0972fda154 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 23:12:32 +0200 Subject: [PATCH 2/8] JustinCC is evil. f7b28dd3 broke script persistence. This fixes it. --- .../Framework/Interfaces/IEntityInventory.cs | 9 ++++++ .../Framework/Scenes/SceneObjectGroup.cs | 1 + .../Framework/Scenes/SceneObjectPart.cs | 3 +- .../Scenes/SceneObjectPartInventory.cs | 28 +++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 7edb43eda2..2e6faa08a1 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -57,6 +57,15 @@ namespace OpenSim.Region.Framework.Interfaces /// Link number for the part void ResetInventoryIDs(); + /// + /// Reset parent object UUID for all the items in the prim's inventory. + /// + /// + /// If this method is called and there are inventory items, then we regard the inventory as having changed. + /// + /// Link number for the part + void ResetObjectID(); + /// /// Change every item in this inventory to a new owner. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f9a8d41b5e..833c9d3dd8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -511,6 +511,7 @@ namespace OpenSim.Region.Framework.Scenes if (node.Attributes["UUID"] != null) { UUID itemid = new UUID(node.Attributes["UUID"].Value); + m_log.DebugFormat("[SCRIPT STATE]: Adding state for oldID {0}", itemid); m_savedScriptState.Add(itemid, node.InnerXml); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 024bdc97bf..95cd26f17e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -500,7 +500,7 @@ namespace OpenSim.Region.Framework.Scenes // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part if (Inventory != null) - Inventory.ResetInventoryIDs(); + Inventory.ResetObjectID(); } } @@ -2763,6 +2763,7 @@ namespace OpenSim.Region.Framework.Scenes UUID = UUID.Random(); LinkNum = linkNum; LocalId = 0; + Inventory.ResetInventoryIDs(); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 53ddb5de27..fbaa7d4872 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -140,6 +140,34 @@ namespace OpenSim.Region.Framework.Scenes } } + public void ResetObjectID() + { + m_items.LockItemsForWrite(true); + + if (Items.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + + HasInventoryChanged = true; + if (m_part.ParentGroup != null) + { + m_part.ParentGroup.HasGroupChanged = true; + } + + IList items = new List(Items.Values); + Items.Clear(); + + foreach (TaskInventoryItem item in items) + { + item.ParentPartID = m_part.UUID; + item.ParentID = m_part.UUID; + Items.Add(item.ItemID, item); + } + m_items.LockItemsForWrite(false); + } + /// /// Change every item in this inventory to a new owner. /// From 670357367e825f194b7993871f1e42af41172a09 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 23:26:53 +0200 Subject: [PATCH 3/8] Removing debug --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 833c9d3dd8..f9a8d41b5e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -511,7 +511,6 @@ namespace OpenSim.Region.Framework.Scenes if (node.Attributes["UUID"] != null) { UUID itemid = new UUID(node.Attributes["UUID"].Value); - m_log.DebugFormat("[SCRIPT STATE]: Adding state for oldID {0}", itemid); m_savedScriptState.Add(itemid, node.InnerXml); } } From 50724292636c1ee68e2d3d215285b52606c6e7f5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 17 Sep 2010 01:16:21 +0100 Subject: [PATCH 4/8] Send KillPackets on the Task queue rather than the State queue Object updates are sent on the task queue. It's possible for an object update to be placed on the client queue before a kill packet comes along. The kill packet would then be placed on the state queue and possibly get sent before the update If the update gets sent afterwards then client get undeletable no owner objects until relog Placing the kills in the task queue should mean that they are received after updates. The kill record prevents subsequent updates getting on the queue Comments state that updates are sent via the state queue but this isn't true. If this was the case this problem might not exist. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 7 ++++++- OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs | 8 +++++++- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2163c12ba6..cede0502fd 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1523,7 +1523,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_entityUpdates.SyncRoot) { m_killRecord.Add(localID); - OutPacket(kill, ThrottleOutPacketType.State); + + // The throttle queue used here must match that being used for updates. Otherwise, there is a + // chance that a kill packet put on a separate queue will be sent to the client before an existing + // update packet on another queue. Receiving updates after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 6232c48105..ca5a7bdc4b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -412,8 +412,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Loops through all of the packet queues for this client and tries to send - /// any outgoing packets, obeying the throttling bucket limits + /// an outgoing packet from each, obeying the throttling bucket limits /// + /// + /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower + /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have + /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the + /// wind queue). + /// /// This function is only called from a synchronous loop in the /// UDPServer so we don't need to bother making this thread safe /// True if any packets were sent, otherwise false diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 56e8c9be54..cb298fdad0 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -500,6 +500,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // FIXME: Implement? } + /// + /// Actually send a packet to a client. + /// + /// internal void SendPacketFinal(OutgoingPacket outgoingPacket) { UDPPacketBuffer buffer = outgoingPacket.Buffer; From e3f153370566e0fd4b6f63a066e016cb52dcdf62 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 17 Sep 2010 01:21:28 +0100 Subject: [PATCH 5/8] Fix build break by replacing Items.LockItemsForWrite() with lock (Items) {} --- .../Scenes/SceneObjectPartInventory.cs | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index fbaa7d4872..7ba30fcafa 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -142,30 +142,29 @@ namespace OpenSim.Region.Framework.Scenes public void ResetObjectID() { - m_items.LockItemsForWrite(true); - - if (Items.Count == 0) + lock (Items) { - m_items.LockItemsForWrite(false); - return; + if (Items.Count == 0) + { + return; + } + + HasInventoryChanged = true; + if (m_part.ParentGroup != null) + { + m_part.ParentGroup.HasGroupChanged = true; + } + + IList items = new List(Items.Values); + Items.Clear(); + + foreach (TaskInventoryItem item in items) + { + item.ParentPartID = m_part.UUID; + item.ParentID = m_part.UUID; + Items.Add(item.ItemID, item); + } } - - HasInventoryChanged = true; - if (m_part.ParentGroup != null) - { - m_part.ParentGroup.HasGroupChanged = true; - } - - IList items = new List(Items.Values); - Items.Clear(); - - foreach (TaskInventoryItem item in items) - { - item.ParentPartID = m_part.UUID; - item.ParentID = m_part.UUID; - Items.Add(item.ItemID, item); - } - m_items.LockItemsForWrite(false); } /// From 860b2a502f797e5822c6705d4639f370f3ac5861 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 16 Sep 2010 17:30:46 -0700 Subject: [PATCH 6/8] Changed SceneObjectGroup to store parts with the fast and thread-safe MapAndArray collection --- OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 4 +- OpenSim/Data/MySQL/MySQLSimulationData.cs | 2 +- OpenSim/Data/SQLite/SQLiteSimulationData.cs | 2 +- .../Data/SQLiteLegacy/SQLiteSimulationData.cs | 2 +- OpenSim/Data/Tests/RegionTests.cs | 14 +- OpenSim/Framework/MapAndArray.cs | 188 +++ .../Avatar/Attachments/AttachmentsModule.cs | 10 +- .../InventoryAccess/InventoryAccessModule.cs | 8 +- .../World/Archiver/ArchiveReadRequest.cs | 6 +- .../World/Objects/BuySell/BuySellModule.cs | 7 +- .../World/WorldMap/MapImageModule.cs | 6 +- .../Framework/Scenes/Scene.Inventory.cs | 8 +- .../Framework/Scenes/Scene.PacketHandlers.cs | 5 +- OpenSim/Region/Framework/Scenes/Scene.cs | 14 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 53 +- .../Scenes/SceneObjectGroup.Inventory.cs | 58 +- .../Framework/Scenes/SceneObjectGroup.cs | 1361 +++++++---------- .../Scenes/SceneObjectPartInventory.cs | 5 +- .../Region/Framework/Scenes/ScenePresence.cs | 2 +- .../Serialization/SceneObjectSerializer.cs | 28 +- .../Framework/Scenes/Tests/SceneGraphTests.cs | 2 +- .../Scenes/Tests/SceneObjectLinkingTests.cs | 36 +- .../Region/Framework/Scenes/UuidGatherer.cs | 5 +- .../CMEntityCollection.cs | 19 +- .../ContentManagementSystem/CMModel.cs | 35 +- .../ContentManagementSystem/CMView.cs | 9 +- .../ContentManagementEntity.cs | 169 +- .../ContentManagementSystem/MetaEntity.cs | 45 +- .../Scripting/Minimodule/SOPObject.cs | 6 +- .../Shared/Api/Implementation/LSL_Api.cs | 91 +- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 11 +- .../Tests/Common/Mock/MockRegionDataPlugin.cs | 2 +- 32 files changed, 1033 insertions(+), 1180 deletions(-) create mode 100644 OpenSim/Framework/MapAndArray.cs diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 8eae0a2a12..1da52b41e4 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -241,7 +241,7 @@ namespace OpenSim.Data.MSSQL /// public void StoreObject(SceneObjectGroup obj, UUID regionUUID) { - _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); + _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length); using (SqlConnection conn = new SqlConnection(m_connectionString)) { @@ -250,7 +250,7 @@ namespace OpenSim.Data.MSSQL try { - foreach (SceneObjectPart sceneObjectPart in obj.Children.Values) + foreach (SceneObjectPart sceneObjectPart in obj.Parts) { //Update prim using (SqlCommand sqlCommand = conn.CreateCommand()) diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 87f6d07063..3450e2fa6b 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -144,7 +144,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); MySqlCommand cmd = dbcon.CreateCommand(); - foreach (SceneObjectPart prim in obj.Children.Values) + foreach (SceneObjectPart prim in obj.Parts) { cmd.Parameters.Clear(); diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index 3e9bc3fe3b..ebe6da8601 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -368,7 +368,7 @@ namespace OpenSim.Data.SQLite lock (ds) { - foreach (SceneObjectPart prim in obj.Children.Values) + foreach (SceneObjectPart prim in obj.Parts) { // m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); addPrim(prim, obj.UUID, regionUUID); diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs index 2dde926fce..ce18a428bb 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs @@ -335,7 +335,7 @@ namespace OpenSim.Data.SQLiteLegacy lock (ds) { - foreach (SceneObjectPart prim in obj.Children.Values) + foreach (SceneObjectPart prim in obj.Parts) { // m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); addPrim(prim, obj.UUID, regionUUID); diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index a081462b73..23d498d6fa 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -232,15 +232,15 @@ namespace OpenSim.Data.Tests sog.AddPart(p2); sog.AddPart(p3); - SceneObjectPart[] parts = sog.GetParts(); + SceneObjectPart[] parts = sog.Parts; Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); db.StoreObject(sog, newregion); List sogs = db.LoadObjects(newregion); Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); SceneObjectGroup newsog = sogs[0]; - - SceneObjectPart[] newparts = newsog.GetParts(); + + SceneObjectPart[] newparts = newsog.Parts; Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))"); @@ -560,7 +560,7 @@ namespace OpenSim.Data.Tests } SceneObjectGroup retsog = FindSOG("Test SOG", region4); - SceneObjectPart[] parts = retsog.GetParts(); + SceneObjectPart[] parts = retsog.Parts; for (int i=0;i<30;i++) { SceneObjectPart cursop = mydic[parts[i].UUID]; @@ -607,7 +607,7 @@ namespace OpenSim.Data.Tests sog.AddPart(p2); sog.AddPart(p3); - SceneObjectPart[] parts = sog.GetParts(); + SceneObjectPart[] parts = sog.Parts; Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); db.StoreObject(sog, newregion); @@ -615,7 +615,7 @@ namespace OpenSim.Data.Tests Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); SceneObjectGroup newsog = sogs[0]; - SceneObjectPart[] newparts = newsog.GetParts(); + SceneObjectPart[] newparts = newsog.Parts; Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); Assert.That(newsog, Constraints.PropertyCompareConstraint(sog) @@ -625,7 +625,7 @@ namespace OpenSim.Data.Tests .IgnoreProperty(x=>x.RegionHandle) .IgnoreProperty(x=>x.RegionUUID) .IgnoreProperty(x=>x.Scene) - .IgnoreProperty(x=>x.Children) + .IgnoreProperty(x=>x.Parts) .IgnoreProperty(x=>x.PassCollision) .IgnoreProperty(x=>x.RootPart)); } diff --git a/OpenSim/Framework/MapAndArray.cs b/OpenSim/Framework/MapAndArray.cs new file mode 100644 index 0000000000..bbe6a9e28e --- /dev/null +++ b/OpenSim/Framework/MapAndArray.cs @@ -0,0 +1,188 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; + +namespace OpenSim.Framework +{ + /// + /// Stores two synchronized collections: a mutable dictionary and an + /// immutable array. Slower inserts/removes than a normal dictionary, + /// but provides safe iteration while maintaining fast hash lookups + /// + /// Key type to use for hash lookups + /// Value type to store + public sealed class MapAndArray + { + private Dictionary m_dict; + private TValue[] m_array; + private object m_syncRoot = new object(); + + /// Number of values currently stored in the collection + public int Count { get { return m_array.Length; } } + /// NOTE: This collection is thread safe. You do not need to + /// acquire a lock to add, remove, or enumerate entries. This + /// synchronization object should only be locked for larger + /// transactions + public object SyncRoot { get { return m_syncRoot; } } + + /// + /// Constructor + /// + public MapAndArray() + { + m_dict = new Dictionary(); + m_array = new TValue[0]; + } + + /// + /// Constructor + /// + /// Initial capacity of the dictionary + public MapAndArray(int capacity) + { + m_dict = new Dictionary(capacity); + m_array = new TValue[0]; + } + + /// + /// Adds a key/value pair to the collection, or updates an existing key + /// with a new value + /// + /// Key to add or update + /// Value to add + /// True if a new key was added, false if an existing key was + /// updated + public bool AddOrReplace(TKey key, TValue value) + { + lock (m_syncRoot) + { + bool containedKey = m_dict.ContainsKey(key); + + m_dict[key] = value; + CreateArray(); + + return !containedKey; + } + } + + /// + /// Adds a key/value pair to the collection. This will throw an + /// exception if the key is already present in the collection + /// + /// Key to add or update + /// Value to add + /// Index of the inserted item + public int Add(TKey key, TValue value) + { + lock (m_syncRoot) + { + m_dict.Add(key, value); + CreateArray(); + return m_array.Length; + } + } + + /// + /// Removes a key/value pair from the collection + /// + /// Key to remove + /// True if the key was found and removed, otherwise false + public bool Remove(TKey key) + { + lock (m_syncRoot) + { + bool removed = m_dict.Remove(key); + CreateArray(); + + return removed; + } + } + + /// + /// Determines whether the collections contains a specified key + /// + /// Key to search for + /// True if the key was found, otherwise false + public bool ContainsKey(TKey key) + { + return m_dict.ContainsKey(key); + } + + /// + /// Gets the value associated with the specified key + /// + /// Key of the value to get + /// Will contain the value associated with the + /// given key if the key is found. If the key is not found it will + /// contain the default value for the type of the value parameter + /// True if the key was found and a value was retrieved, + /// otherwise false + public bool TryGetValue(TKey key, out TValue value) + { + lock (m_syncRoot) + return m_dict.TryGetValue(key, out value); + } + + /// + /// Clears all key/value pairs from the collection + /// + public void Clear() + { + lock (m_syncRoot) + { + m_dict = new Dictionary(); + m_array = new TValue[0]; + } + } + + /// + /// Gets a reference to the immutable array of values stored in this + /// collection. This array is thread safe for iteration + /// + /// A thread safe reference ton an array of all of the stored + /// values + public TValue[] GetArray() + { + return m_array; + } + + private void CreateArray() + { + // Rebuild the array from the dictionary. This method must be + // called from inside a lock + TValue[] array = new TValue[m_dict.Count]; + int i = 0; + + foreach (TValue value in m_dict.Values) + array[i++] = value; + + m_array = array; + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 1ebac42cf7..cb39e46f24 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -567,13 +567,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.RootPart.AttachedAvatar = avatar.UUID; //Anakin Lohner bug #3839 - lock (so.Children) - { - foreach (SceneObjectPart p in so.Children.Values) - { - p.AttachedAvatar = avatar.UUID; - } - } + SceneObjectPart[] parts = so.Parts; + for (int i = 0; i < parts.Length; i++) + parts[i].AttachedAvatar = avatar.UUID; if (so.RootPart.PhysActor != null) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 4c4eeff0e8..c1d6cd3c26 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -594,10 +594,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess rootPart.Name = item.Name; rootPart.Description = item.Description; - List partList = null; - lock (group.Children) - partList = new List(group.Children.Values); - group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { @@ -607,7 +603,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (m_Scene.Permissions.PropagatePermissions()) { - foreach (SceneObjectPart part in partList) + foreach (SceneObjectPart part in group.Parts) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; @@ -618,7 +614,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } - foreach (SceneObjectPart part in partList) + foreach (SceneObjectPart part in group.Parts) { if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 1fba6c2f50..6b538f6876 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -243,11 +243,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // to the same scene (when this is possible). sceneObject.ResetIDs(); - List partList = null; - lock (sceneObject.Children) - partList = new List(sceneObject.Children.Values); - - foreach (SceneObjectPart part in partList) + foreach (SceneObjectPart part in sceneObject.Parts) { if (!ResolveUserUuid(part.CreatorID)) part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs index db50339fec..d91c36c0be 100644 --- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs @@ -128,14 +128,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell group.SetOwnerId(remoteClient.AgentId); group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId); - List partList = null; - - lock (group.Children) - partList = new List(group.Children.Values); - if (m_scene.Permissions.PropagatePermissions()) { - foreach (SceneObjectPart child in partList) + foreach (SceneObjectPart child in group.Parts) { child.Inventory.ChangeInventoryOwner(remoteClient.AgentId); child.TriggerScriptChangedEvent(Changed.OWNER); diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs index 1bd1371c53..c83ac85870 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs @@ -229,11 +229,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap Color mapdotspot = Color.Gray; // Default color when prim color is white // Loop over prim in group - List partList = null; - lock (mapdot.Children) - partList = new List(mapdot.Children.Values); - - foreach (SceneObjectPart part in partList) + foreach (SceneObjectPart part in mapdot.Parts) { if (part == null) continue; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 838c6480b3..8011154521 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2051,9 +2051,7 @@ namespace OpenSim.Region.Framework.Scenes sog.SetGroup(groupID, remoteClient); sog.ScheduleGroupForFullUpdate(); - List partList = null; - lock (sog.Children) - partList = new List(sog.Children.Values); + SceneObjectPart[] partList = sog.Parts; foreach (SceneObjectPart child in partList) child.Inventory.ChangeInventoryOwner(ownerID); @@ -2066,9 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes if (sog.GroupID != groupID) continue; - List partList = null; - lock (sog.Children) - partList = new List(sog.Children.Values); + SceneObjectPart[] partList = sog.Parts; foreach (SceneObjectPart child in partList) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 7788e43c18..4d97db72da 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -161,11 +161,8 @@ namespace OpenSim.Region.Framework.Scenes bool foundPrim = false; SceneObjectGroup sog = ent as SceneObjectGroup; - - List partList = null; - lock (sog.Children) - partList = new List(sog.Children.Values); + SceneObjectPart[] partList = sog.Parts; foreach (SceneObjectPart part in partList) { if (part.LocalId == primLocalID) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8a90bc87b1..fe0ab5b057 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1785,7 +1785,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.ErrorFormat( "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", - group.Children == null ? 0 : group.PrimCount); + group.Parts == null ? 0 : group.PrimCount); } AddRestoredSceneObject(group, true, true); @@ -2091,9 +2091,7 @@ namespace OpenSim.Region.Framework.Scenes group.RemoveScriptInstances(true); } - List partList = null; - lock (group.Children) - partList = new List(group.Children.Values); + SceneObjectPart[] partList = group.Parts; foreach (SceneObjectPart part in partList) { @@ -2465,11 +2463,9 @@ namespace OpenSim.Region.Framework.Scenes // Force allocation of new LocalId // - lock (sceneObject.Children) - { - foreach (SceneObjectPart p in sceneObject.Children.Values) - p.LocalId = 0; - } + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) + parts[i].LocalId = 0; if (sceneObject.IsAttachmentCheckFull()) // Attachment { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 85ff32eb17..28b80bb571 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -348,9 +348,7 @@ namespace OpenSim.Region.Framework.Scenes if (Entities.ContainsKey(sceneObject.UUID)) return false; - List children; - lock (sceneObject.Children) - children = new List(sceneObject.Children.Values); + SceneObjectPart[] children = sceneObject.Parts; // Clamp child prim sizes and add child prims to the m_numPrim count if (m_parentScene.m_clampPrimSize) @@ -369,7 +367,7 @@ namespace OpenSim.Region.Framework.Scenes part.Shape.Scale = scale; } } - m_numPrim += children.Count; + m_numPrim += children.Length; sceneObject.AttachToScene(m_parentScene); @@ -426,15 +424,17 @@ namespace OpenSim.Region.Framework.Scenes lock (SceneObjectGroupsByFullID) { - foreach (SceneObjectPart part in grp.Children.Values) - SceneObjectGroupsByFullID.Remove(part.UUID); + SceneObjectPart[] parts = grp.Parts; + for (int i = 0; i < parts.Length; i++) + SceneObjectGroupsByFullID.Remove(parts[i].UUID); SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); } lock (SceneObjectGroupsByLocalID) { - foreach (SceneObjectPart part in grp.Children.Values) - SceneObjectGroupsByLocalID.Remove(part.LocalId); + SceneObjectPart[] parts = grp.Parts; + for (int i = 0; i < parts.Length; i++) + SceneObjectGroupsByLocalID.Remove(parts[i].LocalId); SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); } @@ -887,11 +887,8 @@ namespace OpenSim.Region.Framework.Scenes if (sog != null) { - lock (sog.Children) - { - if (sog.Children.ContainsKey(fullID)) - return sog; - } + if (sog.ContainsPart(fullID)) + return sog; lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Remove(fullID); @@ -965,7 +962,7 @@ namespace OpenSim.Region.Framework.Scenes { if (entity is SceneObjectGroup) { - foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts()) + foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) { if (p.Name == name) { @@ -1626,14 +1623,8 @@ namespace OpenSim.Region.Framework.Scenes // SceneObjectGroup group = root.ParentGroup; - List newSet = null; - int numChildren = -1; - - lock (group.Children) - { - newSet = new List(group.Children.Values); - numChildren = group.PrimCount; - } + List newSet = new List(group.Parts); + int numChildren = newSet.Count; // If there are prims left in a link set, but the root is // slated for unlink, we need to do this @@ -1711,16 +1702,13 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { SceneObjectGroup sog = ent as SceneObjectGroup; - - lock (sog.Children) + + foreach (SceneObjectPart part in sog.Parts) { - foreach (KeyValuePair subent in sog.Children) + if (part.LocalId == localID) { - if (subent.Value.LocalId == localID) - { - objid = subent.Key; - obj = subent.Value; - } + objid = part.UUID; + obj = part; } } } @@ -1796,8 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes copy.SetOwnerId(AgentID); copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); - List partList = - new List(copy.Children.Values); + SceneObjectPart[] partList = copy.Parts; if (m_parentScene.Permissions.PropagatePermissions()) { @@ -1822,7 +1809,7 @@ namespace OpenSim.Region.Framework.Scenes // think it's selected, so it will never send a deselect... copy.IsSelected = false; - m_numPrim += copy.Children.Count; + m_numPrim += copy.Parts.Length; if (rot != Quaternion.Identity) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 9a01a28b36..a86223c9ba 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -46,13 +46,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void ForceInventoryPersistence() { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.ForceInventoryPersistence(); - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].Inventory.ForceInventoryPersistence(); } /// @@ -64,10 +60,9 @@ namespace OpenSim.Region.Framework.Scenes // Don't start scripts if they're turned off in the region! if (!m_scene.RegionInfo.RegionSettings.DisableScripts) { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); } } @@ -80,13 +75,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstances(bool sceneObjectBeingDeleted) { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted); - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted); } /// @@ -283,8 +274,11 @@ namespace OpenSim.Region.Framework.Scenes PermissionMask.Transfer) | 7; uint ownerMask = 0x7fffffff; - foreach (SceneObjectPart part in m_parts.Values) + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart part = parts[i]; ownerMask &= part.OwnerMask; perms &= part.Inventory.MaskEffectivePermissions(); } @@ -312,39 +306,40 @@ namespace OpenSim.Region.Framework.Scenes public void ApplyNextOwnerPermissions() { - foreach (SceneObjectPart part in m_parts.Values) - { - part.ApplyNextOwnerPermissions(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].ApplyNextOwnerPermissions(); } public string GetStateSnapshot() { Dictionary states = new Dictionary(); - foreach (SceneObjectPart part in m_parts.Values) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart part = parts[i]; foreach (KeyValuePair s in part.Inventory.GetScriptStates()) states[s.Key] = s.Value; } if (states.Count < 1) - return ""; + return String.Empty; XmlDocument xmldoc = new XmlDocument(); XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, - "", ""); + String.Empty, String.Empty); xmldoc.AppendChild(xmlnode); XmlElement rootElement = xmldoc.CreateElement("", "ScriptData", - ""); + String.Empty); xmldoc.AppendChild(rootElement); XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", - ""); + String.Empty); rootElement.AppendChild(wrapper); @@ -424,10 +419,9 @@ namespace OpenSim.Region.Framework.Scenes public void ResumeScripts() { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.ResumeScripts(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].Inventory.ResumeScripts(); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f9a8d41b5e..c984afc5fc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -158,17 +158,14 @@ namespace OpenSim.Region.Framework.Scenes } } - public float scriptScore = 0f; + public float scriptScore; private Vector3 lastPhysGroupPos; private Quaternion lastPhysGroupRot; - private bool m_isBackedUp = false; + private bool m_isBackedUp; - /// - /// The constituent parts of this group - /// - protected Dictionary m_parts = new Dictionary(); + protected MapAndArray m_parts = new MapAndArray(); protected ulong m_regionHandle; protected SceneObjectPart m_rootPart; @@ -177,13 +174,13 @@ namespace OpenSim.Region.Framework.Scenes private Dictionary m_targets = new Dictionary(); private Dictionary m_rotTargets = new Dictionary(); - private bool m_scriptListens_atTarget = false; - private bool m_scriptListens_notAtTarget = false; + private bool m_scriptListens_atTarget; + private bool m_scriptListens_notAtTarget; - private bool m_scriptListens_atRotTarget = false; - private bool m_scriptListens_notAtRotTarget = false; + private bool m_scriptListens_atRotTarget; + private bool m_scriptListens_notAtRotTarget; - internal Dictionary m_savedScriptState = null; + internal Dictionary m_savedScriptState; #region Properties @@ -194,7 +191,7 @@ namespace OpenSim.Region.Framework.Scenes { get { if (RootPart == null) - return ""; + return String.Empty; return RootPart.Name; } set { RootPart.Name = value; } @@ -214,7 +211,7 @@ namespace OpenSim.Region.Framework.Scenes /// public int PrimCount { - get { lock (m_parts) { return m_parts.Count; } } + get { return m_parts.Count; } } protected Quaternion m_rotation = Quaternion.Identity; @@ -236,16 +233,14 @@ namespace OpenSim.Region.Framework.Scenes set { m_rootPart.GroupID = value; } } - /// - /// The parts of this scene object group. You must lock this property before using it. - /// If you're doing anything other than reading values, please take a copy of the values rather than locking - /// the dictionary for the entirety of the operation. This increases liveness and reduces the danger of deadlock - /// If you want to know the number of children, consider using the PrimCount property instead - /// - public Dictionary Children + public SceneObjectPart[] Parts { - get { return m_parts; } - set { m_parts = value; } + get { return m_parts.GetArray(); } + } + + public bool ContainsPart(UUID partID) + { + return m_parts.ContainsKey(partID); } /// @@ -262,13 +257,9 @@ namespace OpenSim.Region.Framework.Scenes set { m_regionHandle = value; - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.RegionHandle = m_regionHandle; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].RegionHandle = value; } } @@ -313,14 +304,10 @@ namespace OpenSim.Region.Framework.Scenes return; } } - - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.GroupPosition = val; - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].GroupPosition = val; //if (m_rootPart.PhysActor != null) //{ @@ -342,14 +329,9 @@ namespace OpenSim.Region.Framework.Scenes { get { return m_rootPart.UUID; } set - { - m_rootPart.UUID = value; - - lock (m_parts) - { - m_parts.Remove(m_rootPart.UUID); - m_parts.Add(m_rootPart.UUID, m_rootPart); - } + { + m_rootPart.UUID = value; + m_parts.AddOrReplace(value, m_rootPart); } } @@ -411,12 +393,12 @@ namespace OpenSim.Region.Framework.Scenes { m_rootPart.PhysActor.Selected = value; // Pass it on to the children. - foreach (SceneObjectPart child in Children.Values) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart child = parts[i]; if (child.PhysActor != null) - { child.PhysActor.Selected = value; - } } } } @@ -519,13 +501,9 @@ namespace OpenSim.Region.Framework.Scenes public void SetFromItemID(UUID AssetId) { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.FromItemID = AssetId; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].FromItemID = AssetId; } public UUID GetFromItemID() @@ -564,23 +542,18 @@ namespace OpenSim.Region.Framework.Scenes if (m_rootPart.LocalId == 0) m_rootPart.LocalId = m_scene.AllocateLocalId(); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (Object.ReferenceEquals(part, m_rootPart)) - { - continue; - } - - if (part.LocalId == 0) - { - part.LocalId = m_scene.AllocateLocalId(); - } - - part.ParentID = m_rootPart.LocalId; - //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); - } + SceneObjectPart part = parts[i]; + if (Object.ReferenceEquals(part, m_rootPart)) + continue; + + if (part.LocalId == 0) + part.LocalId = m_scene.AllocateLocalId(); + + part.ParentID = m_rootPart.LocalId; + //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); } ApplyPhysics(m_scene.m_physicalPrim); @@ -596,22 +569,22 @@ namespace OpenSim.Region.Framework.Scenes Vector3 maxScale = Vector3.Zero; Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - Vector3 partscale = part.Scale; - Vector3 partoffset = part.OffsetPosition; + SceneObjectPart part = parts[i]; + Vector3 partscale = part.Scale; + Vector3 partoffset = part.OffsetPosition; - minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; - minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; - minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; + minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; + minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; + minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; - maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; - maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; - maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; - } + maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; + maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; + maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; } + finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; @@ -627,39 +600,40 @@ namespace OpenSim.Region.Framework.Scenes EntityIntersection result = new EntityIntersection(); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) + SceneObjectPart part = parts[i]; + + // Temporary commented to stop compiler warning + //Vector3 partPosition = + // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); + Quaternion parentrotation = GroupRotation; + + // Telling the prim to raytrace. + //EntityIntersection inter = part.TestIntersection(hRay, parentrotation); + + EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); + + // This may need to be updated to the maximum draw distance possible.. + // We might (and probably will) be checking for prim creation from other sims + // when the camera crosses the border. + float idist = Constants.RegionSize; + + if (inter.HitTF) { - // Temporary commented to stop compiler warning - //Vector3 partPosition = - // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); - Quaternion parentrotation = GroupRotation; - - // Telling the prim to raytrace. - //EntityIntersection inter = part.TestIntersection(hRay, parentrotation); - - EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation,frontFacesOnly, faceCenters); - - // This may need to be updated to the maximum draw distance possible.. - // We might (and probably will) be checking for prim creation from other sims - // when the camera crosses the border. - float idist = Constants.RegionSize; - - if (inter.HitTF) + // We need to find the closest prim to return to the testcaller along the ray + if (inter.distance < idist) { - // We need to find the closest prim to return to the testcaller along the ray - if (inter.distance < idist) - { - result.HitTF = true; - result.ipoint = inter.ipoint; - result.obj = part; - result.normal = inter.normal; - result.distance = inter.distance; - } + result.HitTF = true; + result.ipoint = inter.ipoint; + result.obj = part; + result.normal = inter.normal; + result.distance = inter.distance; } } } + return result; } @@ -678,238 +652,193 @@ namespace OpenSim.Region.Framework.Scenes minY = 256f; minZ = 8192f; - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - Vector3 worldPos = part.GetWorldPosition(); - Vector3 offset = worldPos - AbsolutePosition; - Quaternion worldRot; - if (part.ParentID == 0) - { - worldRot = part.RotationOffset; - } - else - { - worldRot = part.GetWorldRotation(); - } + SceneObjectPart part = parts[i]; - Vector3 frontTopLeft; - Vector3 frontTopRight; - Vector3 frontBottomLeft; - Vector3 frontBottomRight; + Vector3 worldPos = part.GetWorldPosition(); + Vector3 offset = worldPos - AbsolutePosition; + Quaternion worldRot; + if (part.ParentID == 0) + worldRot = part.RotationOffset; + else + worldRot = part.GetWorldRotation(); - Vector3 backTopLeft; - Vector3 backTopRight; - Vector3 backBottomLeft; - Vector3 backBottomRight; + Vector3 frontTopLeft; + Vector3 frontTopRight; + Vector3 frontBottomLeft; + Vector3 frontBottomRight; - // Vector3[] corners = new Vector3[8]; + Vector3 backTopLeft; + Vector3 backTopRight; + Vector3 backBottomLeft; + Vector3 backBottomRight; - Vector3 orig = Vector3.Zero; + Vector3 orig = Vector3.Zero; - frontTopLeft.X = orig.X - (part.Scale.X / 2); - frontTopLeft.Y = orig.Y - (part.Scale.Y / 2); - frontTopLeft.Z = orig.Z + (part.Scale.Z / 2); + frontTopLeft.X = orig.X - (part.Scale.X / 2); + frontTopLeft.Y = orig.Y - (part.Scale.Y / 2); + frontTopLeft.Z = orig.Z + (part.Scale.Z / 2); - frontTopRight.X = orig.X - (part.Scale.X / 2); - frontTopRight.Y = orig.Y + (part.Scale.Y / 2); - frontTopRight.Z = orig.Z + (part.Scale.Z / 2); + frontTopRight.X = orig.X - (part.Scale.X / 2); + frontTopRight.Y = orig.Y + (part.Scale.Y / 2); + frontTopRight.Z = orig.Z + (part.Scale.Z / 2); - frontBottomLeft.X = orig.X - (part.Scale.X / 2); - frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2); - frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2); + frontBottomLeft.X = orig.X - (part.Scale.X / 2); + frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2); + frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2); - frontBottomRight.X = orig.X - (part.Scale.X / 2); - frontBottomRight.Y = orig.Y + (part.Scale.Y / 2); - frontBottomRight.Z = orig.Z - (part.Scale.Z / 2); + frontBottomRight.X = orig.X - (part.Scale.X / 2); + frontBottomRight.Y = orig.Y + (part.Scale.Y / 2); + frontBottomRight.Z = orig.Z - (part.Scale.Z / 2); - backTopLeft.X = orig.X + (part.Scale.X / 2); - backTopLeft.Y = orig.Y - (part.Scale.Y / 2); - backTopLeft.Z = orig.Z + (part.Scale.Z / 2); + backTopLeft.X = orig.X + (part.Scale.X / 2); + backTopLeft.Y = orig.Y - (part.Scale.Y / 2); + backTopLeft.Z = orig.Z + (part.Scale.Z / 2); - backTopRight.X = orig.X + (part.Scale.X / 2); - backTopRight.Y = orig.Y + (part.Scale.Y / 2); - backTopRight.Z = orig.Z + (part.Scale.Z / 2); + backTopRight.X = orig.X + (part.Scale.X / 2); + backTopRight.Y = orig.Y + (part.Scale.Y / 2); + backTopRight.Z = orig.Z + (part.Scale.Z / 2); - backBottomLeft.X = orig.X + (part.Scale.X / 2); - backBottomLeft.Y = orig.Y - (part.Scale.Y / 2); - backBottomLeft.Z = orig.Z - (part.Scale.Z / 2); + backBottomLeft.X = orig.X + (part.Scale.X / 2); + backBottomLeft.Y = orig.Y - (part.Scale.Y / 2); + backBottomLeft.Z = orig.Z - (part.Scale.Z / 2); - backBottomRight.X = orig.X + (part.Scale.X / 2); - backBottomRight.Y = orig.Y + (part.Scale.Y / 2); - backBottomRight.Z = orig.Z - (part.Scale.Z / 2); + backBottomRight.X = orig.X + (part.Scale.X / 2); + backBottomRight.Y = orig.Y + (part.Scale.Y / 2); + backBottomRight.Z = orig.Z - (part.Scale.Z / 2); - //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); - //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); - //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); - //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); - //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); - //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); - //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); - //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); + frontTopLeft = frontTopLeft * worldRot; + frontTopRight = frontTopRight * worldRot; + frontBottomLeft = frontBottomLeft * worldRot; + frontBottomRight = frontBottomRight * worldRot; - //for (int i = 0; i < 8; i++) - //{ - // corners[i] = corners[i] * worldRot; - // corners[i] += offset; - - // if (corners[i].X > maxX) - // maxX = corners[i].X; - // if (corners[i].X < minX) - // minX = corners[i].X; - - // if (corners[i].Y > maxY) - // maxY = corners[i].Y; - // if (corners[i].Y < minY) - // minY = corners[i].Y; - - // if (corners[i].Z > maxZ) - // maxZ = corners[i].Y; - // if (corners[i].Z < minZ) - // minZ = corners[i].Z; - //} - - frontTopLeft = frontTopLeft * worldRot; - frontTopRight = frontTopRight * worldRot; - frontBottomLeft = frontBottomLeft * worldRot; - frontBottomRight = frontBottomRight * worldRot; - - backBottomLeft = backBottomLeft * worldRot; - backBottomRight = backBottomRight * worldRot; - backTopLeft = backTopLeft * worldRot; - backTopRight = backTopRight * worldRot; + backBottomLeft = backBottomLeft * worldRot; + backBottomRight = backBottomRight * worldRot; + backTopLeft = backTopLeft * worldRot; + backTopRight = backTopRight * worldRot; - frontTopLeft += offset; - frontTopRight += offset; - frontBottomLeft += offset; - frontBottomRight += offset; + frontTopLeft += offset; + frontTopRight += offset; + frontBottomLeft += offset; + frontBottomRight += offset; - backBottomLeft += offset; - backBottomRight += offset; - backTopLeft += offset; - backTopRight += offset; + backBottomLeft += offset; + backBottomRight += offset; + backTopLeft += offset; + backTopRight += offset; - //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); - //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); - //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); - //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); - //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); - //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); - //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); - //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); + if (frontTopRight.X > maxX) + maxX = frontTopRight.X; + if (frontTopLeft.X > maxX) + maxX = frontTopLeft.X; + if (frontBottomRight.X > maxX) + maxX = frontBottomRight.X; + if (frontBottomLeft.X > maxX) + maxX = frontBottomLeft.X; - if (frontTopRight.X > maxX) - maxX = frontTopRight.X; - if (frontTopLeft.X > maxX) - maxX = frontTopLeft.X; - if (frontBottomRight.X > maxX) - maxX = frontBottomRight.X; - if (frontBottomLeft.X > maxX) - maxX = frontBottomLeft.X; + if (backTopRight.X > maxX) + maxX = backTopRight.X; + if (backTopLeft.X > maxX) + maxX = backTopLeft.X; + if (backBottomRight.X > maxX) + maxX = backBottomRight.X; + if (backBottomLeft.X > maxX) + maxX = backBottomLeft.X; - if (backTopRight.X > maxX) - maxX = backTopRight.X; - if (backTopLeft.X > maxX) - maxX = backTopLeft.X; - if (backBottomRight.X > maxX) - maxX = backBottomRight.X; - if (backBottomLeft.X > maxX) - maxX = backBottomLeft.X; + if (frontTopRight.X < minX) + minX = frontTopRight.X; + if (frontTopLeft.X < minX) + minX = frontTopLeft.X; + if (frontBottomRight.X < minX) + minX = frontBottomRight.X; + if (frontBottomLeft.X < minX) + minX = frontBottomLeft.X; - if (frontTopRight.X < minX) - minX = frontTopRight.X; - if (frontTopLeft.X < minX) - minX = frontTopLeft.X; - if (frontBottomRight.X < minX) - minX = frontBottomRight.X; - if (frontBottomLeft.X < minX) - minX = frontBottomLeft.X; + if (backTopRight.X < minX) + minX = backTopRight.X; + if (backTopLeft.X < minX) + minX = backTopLeft.X; + if (backBottomRight.X < minX) + minX = backBottomRight.X; + if (backBottomLeft.X < minX) + minX = backBottomLeft.X; - if (backTopRight.X < minX) - minX = backTopRight.X; - if (backTopLeft.X < minX) - minX = backTopLeft.X; - if (backBottomRight.X < minX) - minX = backBottomRight.X; - if (backBottomLeft.X < minX) - minX = backBottomLeft.X; + // + if (frontTopRight.Y > maxY) + maxY = frontTopRight.Y; + if (frontTopLeft.Y > maxY) + maxY = frontTopLeft.Y; + if (frontBottomRight.Y > maxY) + maxY = frontBottomRight.Y; + if (frontBottomLeft.Y > maxY) + maxY = frontBottomLeft.Y; - // - if (frontTopRight.Y > maxY) - maxY = frontTopRight.Y; - if (frontTopLeft.Y > maxY) - maxY = frontTopLeft.Y; - if (frontBottomRight.Y > maxY) - maxY = frontBottomRight.Y; - if (frontBottomLeft.Y > maxY) - maxY = frontBottomLeft.Y; + if (backTopRight.Y > maxY) + maxY = backTopRight.Y; + if (backTopLeft.Y > maxY) + maxY = backTopLeft.Y; + if (backBottomRight.Y > maxY) + maxY = backBottomRight.Y; + if (backBottomLeft.Y > maxY) + maxY = backBottomLeft.Y; - if (backTopRight.Y > maxY) - maxY = backTopRight.Y; - if (backTopLeft.Y > maxY) - maxY = backTopLeft.Y; - if (backBottomRight.Y > maxY) - maxY = backBottomRight.Y; - if (backBottomLeft.Y > maxY) - maxY = backBottomLeft.Y; + if (frontTopRight.Y < minY) + minY = frontTopRight.Y; + if (frontTopLeft.Y < minY) + minY = frontTopLeft.Y; + if (frontBottomRight.Y < minY) + minY = frontBottomRight.Y; + if (frontBottomLeft.Y < minY) + minY = frontBottomLeft.Y; - if (frontTopRight.Y < minY) - minY = frontTopRight.Y; - if (frontTopLeft.Y < minY) - minY = frontTopLeft.Y; - if (frontBottomRight.Y < minY) - minY = frontBottomRight.Y; - if (frontBottomLeft.Y < minY) - minY = frontBottomLeft.Y; + if (backTopRight.Y < minY) + minY = backTopRight.Y; + if (backTopLeft.Y < minY) + minY = backTopLeft.Y; + if (backBottomRight.Y < minY) + minY = backBottomRight.Y; + if (backBottomLeft.Y < minY) + minY = backBottomLeft.Y; - if (backTopRight.Y < minY) - minY = backTopRight.Y; - if (backTopLeft.Y < minY) - minY = backTopLeft.Y; - if (backBottomRight.Y < minY) - minY = backBottomRight.Y; - if (backBottomLeft.Y < minY) - minY = backBottomLeft.Y; + // + if (frontTopRight.Z > maxZ) + maxZ = frontTopRight.Z; + if (frontTopLeft.Z > maxZ) + maxZ = frontTopLeft.Z; + if (frontBottomRight.Z > maxZ) + maxZ = frontBottomRight.Z; + if (frontBottomLeft.Z > maxZ) + maxZ = frontBottomLeft.Z; - // - if (frontTopRight.Z > maxZ) - maxZ = frontTopRight.Z; - if (frontTopLeft.Z > maxZ) - maxZ = frontTopLeft.Z; - if (frontBottomRight.Z > maxZ) - maxZ = frontBottomRight.Z; - if (frontBottomLeft.Z > maxZ) - maxZ = frontBottomLeft.Z; + if (backTopRight.Z > maxZ) + maxZ = backTopRight.Z; + if (backTopLeft.Z > maxZ) + maxZ = backTopLeft.Z; + if (backBottomRight.Z > maxZ) + maxZ = backBottomRight.Z; + if (backBottomLeft.Z > maxZ) + maxZ = backBottomLeft.Z; - if (backTopRight.Z > maxZ) - maxZ = backTopRight.Z; - if (backTopLeft.Z > maxZ) - maxZ = backTopLeft.Z; - if (backBottomRight.Z > maxZ) - maxZ = backBottomRight.Z; - if (backBottomLeft.Z > maxZ) - maxZ = backBottomLeft.Z; + if (frontTopRight.Z < minZ) + minZ = frontTopRight.Z; + if (frontTopLeft.Z < minZ) + minZ = frontTopLeft.Z; + if (frontBottomRight.Z < minZ) + minZ = frontBottomRight.Z; + if (frontBottomLeft.Z < minZ) + minZ = frontBottomLeft.Z; - if (frontTopRight.Z < minZ) - minZ = frontTopRight.Z; - if (frontTopLeft.Z < minZ) - minZ = frontTopLeft.Z; - if (frontBottomRight.Z < minZ) - minZ = frontBottomRight.Z; - if (frontBottomLeft.Z < minZ) - minZ = frontBottomLeft.Z; - - if (backTopRight.Z < minZ) - minZ = backTopRight.Z; - if (backTopLeft.Z < minZ) - minZ = backTopLeft.Z; - if (backBottomRight.Z < minZ) - minZ = backBottomRight.Z; - if (backBottomLeft.Z < minZ) - minZ = backBottomLeft.Z; - } + if (backTopRight.Z < minZ) + minZ = backTopRight.Z; + if (backTopLeft.Z < minZ) + minZ = backTopLeft.Z; + if (backBottomRight.Z < minZ) + minZ = backBottomRight.Z; + if (backBottomLeft.Z < minZ) + minZ = backBottomLeft.Z; } } @@ -949,17 +878,12 @@ namespace OpenSim.Region.Framework.Scenes XmlDocument doc = new XmlDocument(); Dictionary states = new Dictionary(); - // Capture script state while holding the lock - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - Dictionary pstates = part.Inventory.GetScriptStates(); - foreach (UUID itemid in pstates.Keys) - { - states.Add(itemid, pstates[itemid]); - } - } + Dictionary pstates = parts[i].Inventory.GetScriptStates(); + foreach (KeyValuePair kvp in pstates) + states.Add(kvp.Key, kvp.Value); } if (states.Count > 0) @@ -1005,15 +929,10 @@ namespace OpenSim.Region.Framework.Scenes AbsolutePosition = detachedpos; m_rootPart.AttachedAvatar = UUID.Zero; - - //Anakin Lohner bug #3839 - lock (m_parts) - { - foreach (SceneObjectPart p in m_parts.Values) - { - p.AttachedAvatar = UUID.Zero; - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].AttachedAvatar = UUID.Zero; m_rootPart.SetParentLocalId(0); SetAttachmentPoint((byte)0); @@ -1038,15 +957,10 @@ namespace OpenSim.Region.Framework.Scenes } m_rootPart.AttachedAvatar = UUID.Zero; - - //Anakin Lohner bug #3839 - lock (m_parts) - { - foreach (SceneObjectPart p in m_parts.Values) - { - p.AttachedAvatar = UUID.Zero; - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].AttachedAvatar = UUID.Zero; m_rootPart.SetParentLocalId(0); //m_rootPart.SetAttachmentPoint((byte)0); @@ -1069,13 +983,9 @@ namespace OpenSim.Region.Framework.Scenes public override void UpdateMovement() { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.UpdateMovement(); - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].UpdateMovement(); } public ushort GetTimeDilation() @@ -1108,8 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes part.ParentID = 0; part.LinkNum = 0; - lock (m_parts) - m_parts.Add(m_rootPart.UUID, m_rootPart); + m_parts.Add(m_rootPart.UUID, m_rootPart); } /// @@ -1118,16 +1027,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddPart(SceneObjectPart part) { - lock (m_parts) - { - part.SetParent(this); - m_parts.Add(part.UUID, part); - - part.LinkNum = m_parts.Count; - - if (part.LinkNum == 2 && RootPart != null) - RootPart.LinkNum = 1; - } + part.SetParent(this); + part.LinkNum = m_parts.Add(part.UUID, part); + if (part.LinkNum == 2 && RootPart != null) + RootPart.LinkNum = 1; } /// @@ -1135,28 +1038,20 @@ namespace OpenSim.Region.Framework.Scenes /// private void UpdateParentIDs() { - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part.UUID != m_rootPart.UUID) - { - part.ParentID = m_rootPart.LocalId; - } - } + SceneObjectPart part = parts[i]; + if (part.UUID != m_rootPart.UUID) + part.ParentID = m_rootPart.LocalId; } } public void RegenerateFullIDs() { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.UUID = UUID.Random(); - - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].UUID = UUID.Random(); } // helper provided for parts. @@ -1189,7 +1084,7 @@ namespace OpenSim.Region.Framework.Scenes // teravus: AbsolutePosition is NOT a normal property! // the code in the getter of AbsolutePosition is significantly different then the code in the setter! - + // jhurliman: Then why is it a property instead of two methods? } public UUID GetPartsFullID(uint localID) @@ -1237,19 +1132,15 @@ namespace OpenSim.Region.Framework.Scenes /// If true then deletion is not broadcast to clients public void DeleteGroupFromScene(bool silent) { - List parts; - - lock (m_parts) - parts = m_parts.Values.ToList(); - - foreach (SceneObjectPart part in parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart part = parts[i]; + Scene.ForEachScenePresence(delegate(ScenePresence avatar) { if (avatar.ParentID == LocalId) - { avatar.StandUp(); - } if (!silent) { @@ -1283,16 +1174,15 @@ namespace OpenSim.Region.Framework.Scenes scriptEvents aggregateScriptEvents = 0; - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part == null) - continue; - if (part != RootPart) - part.Flags = objectflagupdate; - aggregateScriptEvents |= part.AggregateScriptEvents; - } + SceneObjectPart part = parts[i]; + if (part == null) + continue; + if (part != RootPart) + part.Flags = objectflagupdate; + aggregateScriptEvents |= part.AggregateScriptEvents; } m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); @@ -1335,26 +1225,22 @@ namespace OpenSim.Region.Framework.Scenes /// public void ApplyPhysics(bool m_physicalPrim) { - lock (m_parts) + // Apply physics to the root prim + m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); + + // Apply physics to child prims + SceneObjectPart[] parts = m_parts.GetArray(); + if (parts.Length > 1) { - if (m_parts.Count > 1) + for (int i = 0; i < parts.Length; i++) { - m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); - foreach (SceneObjectPart part in m_parts.Values) - { - if (part.LocalId != m_rootPart.LocalId) - { - part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); - } - } - - // Hack to get the physics scene geometries in the right spot - ResetChildPrimPhysicsPositions(); - } - else - { - m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); + SceneObjectPart part = parts[i]; + if (part.LocalId != m_rootPart.LocalId) + part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); } + + // Hack to get the physics scene geometries in the right spot + ResetChildPrimPhysicsPositions(); } } @@ -1365,13 +1251,9 @@ namespace OpenSim.Region.Framework.Scenes public void ForEachPart(Action whatToDo) { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - whatToDo(part); - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + whatToDo(parts[i]); } #region Events @@ -1476,14 +1358,12 @@ namespace OpenSim.Region.Framework.Scenes RootPart.SendFullUpdate( remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part != RootPart) - part.SendFullUpdate( - remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); - } + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.SendFullUpdate(remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); } } @@ -1498,7 +1378,7 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); dupe.m_isBackedUp = false; - dupe.m_parts = new Dictionary(); + dupe.m_parts.Clear(); // Warning, The following code related to previousAttachmentStatus is needed so that clones of // attachments do not bordercross while they're being duplicated. This is hacktastic! @@ -1527,12 +1407,7 @@ namespace OpenSim.Region.Framework.Scenes if (userExposed) dupe.m_rootPart.TrimPermissions(); - List partList; - - lock (m_parts) - { - partList = new List(m_parts.Values); - } + List partList = new List(m_parts.GetArray()); partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) { @@ -1837,17 +1712,10 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) { - SceneObjectPart newPart = null; - - lock (m_parts) - { - newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); - newPart.SetParent(this); - m_parts.Add(newPart.UUID, newPart); - } + SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); + AddPart(newPart); SetPartAsNonRoot(newPart); - return newPart; } @@ -1859,9 +1727,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void ResetIDs() { - lock (m_parts) + lock (m_parts.SyncRoot) { - List partsList = new List(m_parts.Values); + List partsList = new List(m_parts.GetArray()); m_parts.Clear(); foreach (SceneObjectPart part in partsList) { @@ -1877,7 +1745,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) { - remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, @@ -1922,12 +1789,10 @@ namespace OpenSim.Region.Framework.Scenes lastPhysGroupRot = GroupRotation; } - List partList = null; - lock (m_parts) - partList = new List(m_parts.Values); - - foreach (SceneObjectPart part in partList) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart part = parts[i]; if (!IsSelected) part.UpdateLookAt(); part.SendScheduledUpdates(); @@ -1940,27 +1805,22 @@ namespace OpenSim.Region.Framework.Scenes RootPart.AddFullUpdateToAvatar(presence); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part != RootPart) - part.AddFullUpdateToAvatar(presence); - } + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.AddFullUpdateToAvatar(presence); } } public void ScheduleTerseUpdateToAvatar(ScenePresence presence) { // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); - - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.AddTerseUpdateToAvatar(presence); - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].AddTerseUpdateToAvatar(presence); } /// @@ -1974,13 +1834,12 @@ namespace OpenSim.Region.Framework.Scenes checkAtTargets(); RootPart.ScheduleFullUpdate(); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part != RootPart) - part.ScheduleFullUpdate(); - } + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.ScheduleFullUpdate(); } } @@ -1990,14 +1849,10 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleGroupForTerseUpdate() { // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); - - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.ScheduleTerseUpdate(); - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].ScheduleTerseUpdate(); } /// @@ -2012,13 +1867,12 @@ namespace OpenSim.Region.Framework.Scenes RootPart.SendFullUpdateToAllClients(); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part != RootPart) - part.SendFullUpdateToAllClients(); - } + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.SendFullUpdateToAllClients(); } } @@ -2051,14 +1905,10 @@ namespace OpenSim.Region.Framework.Scenes { if (IsDeleted) return; - - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - part.SendTerseUpdateToAllClients(); - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].SendTerseUpdateToAllClients(); } #endregion @@ -2072,15 +1922,11 @@ namespace OpenSim.Region.Framework.Scenes /// null if no child part with that linknum or child part public SceneObjectPart GetLinkNumPart(int linknum) { - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part.LinkNum == linknum) - { - return part; - } - } + if (parts[i].LinkNum == linknum) + return parts[i]; } return null; @@ -2094,8 +1940,7 @@ namespace OpenSim.Region.Framework.Scenes public SceneObjectPart GetChildPart(UUID primID) { SceneObjectPart childPart; - lock (m_parts) - m_parts.TryGetValue(primID, out childPart); + m_parts.TryGetValue(primID, out childPart); return childPart; } @@ -2106,17 +1951,11 @@ namespace OpenSim.Region.Framework.Scenes /// null if a child part with the local ID was not found public SceneObjectPart GetChildPart(uint localID) { - //m_log.DebugFormat("Entered looking for {0}", localID); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - //m_log.DebugFormat("Found {0}", part.LocalId); - if (part.LocalId == localID) - { - return part; - } - } + if (parts[i].LocalId == localID) + return parts[i]; } return null; @@ -2130,13 +1969,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool HasChildPrim(UUID primID) { - lock (m_parts) - { - if (m_parts.ContainsKey(primID)) - return true; - } - - return false; + return m_parts.ContainsKey(primID); } /// @@ -2147,17 +1980,11 @@ namespace OpenSim.Region.Framework.Scenes /// public bool HasChildPrim(uint localID) { - //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - //m_log.DebugFormat("Found {0}", part.LocalId); - if (part.LocalId == localID) - { - return true; - } - } + if (parts[i].LocalId == localID) + return true; } return false; @@ -2208,19 +2035,21 @@ namespace OpenSim.Region.Framework.Scenes if (m_rootPart.LinkNum == 0) m_rootPart.LinkNum = 1; - lock (m_parts) + lock (m_parts.SyncRoot) { m_parts.Add(linkPart.UUID, linkPart); // Insert in terms of link numbers, the new links // before the current ones (with the exception of // the root prim. Shuffle the old ones up - foreach (KeyValuePair kvp in m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - if (kvp.Value.LinkNum != 1) + SceneObjectPart part = parts[i]; + if (part.LinkNum != 1) { // Don't update root prim link number - kvp.Value.LinkNum += objectGroup.PrimCount; + part.LinkNum += objectGroup.PrimCount; } } @@ -2232,29 +2061,26 @@ namespace OpenSim.Region.Framework.Scenes //if (linkPart.PhysActor != null) //{ // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); - + //linkPart.PhysActor = null; //} //TODO: rest of parts int linkNum = 3; - foreach (SceneObjectPart part in objectGroup.Children.Values) + SceneObjectPart[] ogParts = objectGroup.Parts; + for (int i = 0; i < ogParts.Length; i++) { + SceneObjectPart part = ogParts[i]; if (part.UUID != objectGroup.m_rootPart.UUID) - { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); - } part.ClearUndoState(); } } m_scene.UnlinkSceneObject(objectGroup, true); objectGroup.m_isDeleted = true; - - lock (objectGroup.m_parts) - { - objectGroup.m_parts.Clear(); - } + + objectGroup.m_parts.Clear(); // Can't do this yet since backup still makes use of the root part without any synchronization // objectGroup.m_rootPart = null; @@ -2324,20 +2150,24 @@ namespace OpenSim.Region.Framework.Scenes Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object - lock (m_parts) + lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); - - if (m_parts.Count == 1 && RootPart != null) //Single prim is left + + SceneObjectPart[] parts = m_parts.GetArray(); + + if (parts.Length == 1 && RootPart != null) { + // Single prim left RootPart.LinkNum = 0; } else { - foreach (SceneObjectPart p in m_parts.Values) + for (int i = 0; i < parts.Length; i++) { - if (p.LinkNum > linkPart.LinkNum) - p.LinkNum--; + SceneObjectPart part = parts[i]; + if (part.LinkNum > linkPart.LinkNum) + part.LinkNum--; } } } @@ -2409,7 +2239,6 @@ namespace OpenSim.Region.Framework.Scenes part.SetParent(this); part.ParentID = m_rootPart.LocalId; - // Caller locks m_parts for us m_parts.Add(part.UUID, part); part.LinkNum = linkNum; @@ -2662,24 +2491,21 @@ namespace OpenSim.Region.Framework.Scenes if (selectionPart != null) { - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) + SceneObjectPart part = parts[i]; + if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || + part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || + part.Scale.Z > m_scene.RegionInfo.PhysPrimMax) { - if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || - part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || - part.Scale.Z > m_scene.RegionInfo.PhysPrimMax) - { - UsePhysics = false; // Reset physics - break; - } - } - - foreach (SceneObjectPart part in m_parts.Values) - { - part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); + UsePhysics = false; // Reset physics + break; } } + + for (int i = 0; i < parts.Length; i++) + parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); } } @@ -2692,18 +2518,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Get the parts of this scene object - /// - /// - public SceneObjectPart[] GetParts() - { - int numParts = Children.Count; - SceneObjectPart[] partArray = new SceneObjectPart[numParts]; - Children.Values.CopyTo(partArray, 0); - return partArray; - } - /// /// Update the texture entry for this part /// @@ -2721,12 +2535,9 @@ namespace OpenSim.Region.Framework.Scenes public void UpdatePermissions(UUID AgentID, byte field, uint localID, uint mask, byte addRemTF) { - List partList = null; - lock (m_parts) - partList = new List(m_parts.Values); - - foreach (SceneObjectPart part in partList) - part.UpdatePermissions(AgentID, field, localID, mask, addRemTF); + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF); HasGroupChanged = true; } @@ -2829,77 +2640,77 @@ namespace OpenSim.Region.Framework.Scenes float y = (scale.Y / part.Scale.Y); float z = (scale.Z / part.Scale.Z); - lock (m_parts) + SceneObjectPart[] parts; + if (x > 1.0f || y > 1.0f || z > 1.0f) { - if (x > 1.0f || y > 1.0f || z > 1.0f) + parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart obPart in m_parts.Values) + SceneObjectPart obPart = parts[i]; + if (obPart.UUID != m_rootPart.UUID) { - if (obPart.UUID != m_rootPart.UUID) + obPart.IgnoreUndoUpdate = true; + Vector3 oldSize = new Vector3(obPart.Scale); + + float f = 1.0f; + float a = 1.0f; + + if (part.PhysActor != null && part.PhysActor.IsPhysical) { - obPart.IgnoreUndoUpdate = true; - Vector3 oldSize = new Vector3(obPart.Scale); - - float f = 1.0f; - float a = 1.0f; - - if (part.PhysActor != null && part.PhysActor.IsPhysical) + if (oldSize.X * x > m_scene.m_maxPhys) { - if (oldSize.X*x > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y*y > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z*z > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } + f = m_scene.m_maxPhys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; } - else + if (oldSize.Y * y > m_scene.m_maxPhys) { - if (oldSize.X*x > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y*y > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z*z > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } + f = m_scene.m_maxPhys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Z * z > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); } + else + { + if (oldSize.X * x > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Y * y > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Z * z > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } + } + obPart.IgnoreUndoUpdate = false; + obPart.StoreUndoState(); } } } @@ -2910,27 +2721,26 @@ namespace OpenSim.Region.Framework.Scenes prevScale.Z *= z; part.Resize(prevScale); - lock (m_parts) + parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart obPart in m_parts.Values) + SceneObjectPart obPart = parts[i]; + obPart.IgnoreUndoUpdate = true; + if (obPart.UUID != m_rootPart.UUID) { - obPart.IgnoreUndoUpdate = true; - if (obPart.UUID != m_rootPart.UUID) - { - Vector3 currentpos = new Vector3(obPart.OffsetPosition); - currentpos.X *= x; - currentpos.Y *= y; - currentpos.Z *= z; - Vector3 newSize = new Vector3(obPart.Scale); - newSize.X *= x; - newSize.Y *= y; - newSize.Z *= z; - obPart.Resize(newSize); - obPart.UpdateOffSet(currentpos); - } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); + Vector3 currentpos = new Vector3(obPart.OffsetPosition); + currentpos.X *= x; + currentpos.Y *= y; + currentpos.Z *= z; + Vector3 newSize = new Vector3(obPart.Scale); + newSize.X *= x; + newSize.Y *= y; + newSize.Z *= z; + obPart.Resize(newSize); + obPart.UpdateOffSet(currentpos); } + obPart.IgnoreUndoUpdate = false; + obPart.StoreUndoState(); } if (part.PhysActor != null) @@ -2956,10 +2766,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupPosition(Vector3 pos) { - foreach (SceneObjectPart part in Children.Values) - { - part.StoreUndoState(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { if (IsAttachment) @@ -2994,10 +2804,11 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateSinglePosition(Vector3 pos, uint localID) { SceneObjectPart part = GetChildPart(localID); - foreach (SceneObjectPart parts in Children.Values) - { - parts.StoreUndoState(); - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + if (part != null) { if (part.UUID == m_rootPart.UUID) @@ -3019,10 +2830,10 @@ namespace OpenSim.Region.Framework.Scenes /// private void UpdateRootPosition(Vector3 pos) { - foreach (SceneObjectPart part in Children.Values) - { - part.StoreUndoState(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); Vector3 oldPos = new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, @@ -3034,15 +2845,12 @@ namespace OpenSim.Region.Framework.Scenes axDiff *= Quaternion.Inverse(partRotation); diff = axDiff; - lock (m_parts) + parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart obPart in m_parts.Values) - { - if (obPart.UUID != m_rootPart.UUID) - { - obPart.OffsetPosition = obPart.OffsetPosition + diff; - } - } + SceneObjectPart obPart = parts[i]; + if (obPart.UUID != m_rootPart.UUID) + obPart.OffsetPosition = obPart.OffsetPosition + diff; } AbsolutePosition = newPos; @@ -3066,10 +2874,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationR(Quaternion rot) { - foreach (SceneObjectPart parts in Children.Values) - { - parts.StoreUndoState(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + m_rootPart.UpdateRotation(rot); PhysicsActor actor = m_rootPart.PhysActor; @@ -3090,10 +2898,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) { - foreach (SceneObjectPart parts in Children.Values) - { - parts.StoreUndoState(); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + m_rootPart.UpdateRotation(rot); PhysicsActor actor = m_rootPart.PhysActor; @@ -3117,10 +2925,11 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateSingleRotation(Quaternion rot, uint localID) { SceneObjectPart part = GetChildPart(localID); - foreach (SceneObjectPart parts in Children.Values) - { - parts.StoreUndoState(); - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].StoreUndoState(); + if (part != null) { if (part.UUID == m_rootPart.UUID) @@ -3177,33 +2986,35 @@ namespace OpenSim.Region.Framework.Scenes m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); } - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart prim in m_parts.Values) + SceneObjectPart prim = parts[i]; + if (prim.UUID != m_rootPart.UUID) { - if (prim.UUID != m_rootPart.UUID) - { - prim.IgnoreUndoUpdate = true; - Vector3 axPos = prim.OffsetPosition; - axPos *= oldParentRot; - axPos *= Quaternion.Inverse(axRot); - prim.OffsetPosition = axPos; - Quaternion primsRot = prim.RotationOffset; - Quaternion newRot = primsRot * oldParentRot; - newRot *= Quaternion.Inverse(axRot); - prim.RotationOffset = newRot; - prim.ScheduleTerseUpdate(); - } + prim.IgnoreUndoUpdate = true; + Vector3 axPos = prim.OffsetPosition; + axPos *= oldParentRot; + axPos *= Quaternion.Inverse(axRot); + prim.OffsetPosition = axPos; + Quaternion primsRot = prim.RotationOffset; + Quaternion newRot = primsRot * oldParentRot; + newRot *= Quaternion.Inverse(axRot); + prim.RotationOffset = newRot; + prim.ScheduleTerseUpdate(); } } - foreach (SceneObjectPart childpart in Children.Values) + + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart childpart = parts[i]; if (childpart != m_rootPart) { childpart.IgnoreUndoUpdate = false; childpart.StoreUndoState(); } } + m_rootPart.ScheduleTerseUpdate(); } @@ -3324,17 +3135,10 @@ namespace OpenSim.Region.Framework.Scenes if (atTargets.Count > 0) { - uint[] localids = new uint[0]; - lock (m_parts) - { - localids = new uint[m_parts.Count]; - int cntr = 0; - foreach (SceneObjectPart part in m_parts.Values) - { - localids[cntr] = part.LocalId; - cntr++; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + uint[] localids = new uint[parts.Length]; + for (int i = 0; i < parts.Length; i++) + localids[i] = parts[i].LocalId; for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3352,17 +3156,10 @@ namespace OpenSim.Region.Framework.Scenes if (m_scriptListens_notAtTarget && !at_target) { //trigger not_at_target - uint[] localids = new uint[0]; - lock (m_parts) - { - localids = new uint[m_parts.Count]; - int cntr = 0; - foreach (SceneObjectPart part in m_parts.Values) - { - localids[cntr] = part.LocalId; - cntr++; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + uint[] localids = new uint[parts.Length]; + for (int i = 0; i < parts.Length; i++) + localids[i] = parts[i].LocalId; for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3403,17 +3200,10 @@ namespace OpenSim.Region.Framework.Scenes if (atRotTargets.Count > 0) { - uint[] localids = new uint[0]; - lock (m_parts) - { - localids = new uint[m_parts.Count]; - int cntr = 0; - foreach (SceneObjectPart part in m_parts.Values) - { - localids[cntr] = part.LocalId; - cntr++; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + uint[] localids = new uint[parts.Length]; + for (int i = 0; i < parts.Length; i++) + localids[i] = parts[i].LocalId; for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3431,17 +3221,10 @@ namespace OpenSim.Region.Framework.Scenes if (m_scriptListens_notAtRotTarget && !at_Rottarget) { //trigger not_at_target - uint[] localids = new uint[0]; - lock (m_parts) - { - localids = new uint[m_parts.Count]; - int cntr = 0; - foreach (SceneObjectPart part in m_parts.Values) - { - localids[cntr] = part.LocalId; - cntr++; - } - } + SceneObjectPart[] parts = m_parts.GetArray(); + uint[] localids = new uint[parts.Length]; + for (int i = 0; i < parts.Length; i++) + localids[i] = parts[i].LocalId; for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3455,40 +3238,36 @@ namespace OpenSim.Region.Framework.Scenes public float GetMass() { float retmass = 0f; - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - { - retmass += part.GetMass(); - } - } + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + retmass += parts[i].GetMass(); + return retmass; } public void CheckSculptAndLoad() { - lock (m_parts) + if (IsDeleted) + return; + if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) + return; + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - if (!IsDeleted) + SceneObjectPart part = parts[i]; + if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero) { - if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == 0) + // check if a previously decoded sculpt map has been cached + if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString()))) { - foreach (SceneObjectPart part in m_parts.Values) - { - if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero) - { - // check if a previously decoded sculpt map has been cached - if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString()))) - { - part.SculptTextureCallback(part.Shape.SculptTexture, null); - } - else - { - m_scene.AssetService.Get( - part.Shape.SculptTexture.ToString(), part, AssetReceived); - } - } - } + part.SculptTextureCallback(part.Shape.SculptTexture, null); + } + else + { + m_scene.AssetService.Get( + part.Shape.SculptTexture.ToString(), part, AssetReceived); } } } @@ -3512,15 +3291,12 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetGroup(UUID GroupID, IClientAPI client) { - lock (m_parts) + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in m_parts.Values) - { - part.SetGroup(GroupID, client); - part.Inventory.ChangeInventoryGroup(GroupID); - } - - HasGroupChanged = true; + SceneObjectPart part = parts[i]; + part.SetGroup(GroupID, client); + part.Inventory.ChangeInventoryGroup(GroupID); } // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled @@ -3530,10 +3306,9 @@ namespace OpenSim.Region.Framework.Scenes public void TriggerScriptChangedEvent(Changed val) { - foreach (SceneObjectPart part in Children.Values) - { - part.TriggerScriptChangedEvent(val); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].TriggerScriptChangedEvent(val); } public override string ToString() @@ -3543,11 +3318,9 @@ namespace OpenSim.Region.Framework.Scenes public void SetAttachmentPoint(byte point) { - lock (m_parts) - { - foreach (SceneObjectPart part in m_parts.Values) - part.SetAttachmentPoint(point); - } + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + parts[i].SetAttachmentPoint(point); } #region ISceneObject diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 53ddb5de27..0e3daf764a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -603,10 +603,7 @@ namespace OpenSim.Region.Framework.Scenes rootPart.Name = item.Name; rootPart.Description = item.Description; - List partList = null; - - lock (group.Children) - partList = new List(group.Children.Values); + SceneObjectPart[] partList = group.Parts; group.SetGroup(m_part.GroupID, null); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a77f38c01a..a4533fa6be 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. // Get our own copy of the part array, and sort into the order we want to test - SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); + SceneObjectPart[] partArray = targetPart.ParentGroup.Parts; Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) { // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 5bdaa17f69..f5f6b9023f 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -158,16 +158,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteEndElement(); writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); - lock (sceneObject.Children) + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in sceneObject.Children.Values) + SceneObjectPart part = parts[i]; + if (part.UUID != sceneObject.RootPart.UUID) { - if (part.UUID != sceneObject.RootPart.UUID) - { - writer.WriteStartElement(String.Empty, "Part", String.Empty); - ToOriginalXmlFormat(part, writer); - writer.WriteEndElement(); - } + writer.WriteStartElement(String.Empty, "Part", String.Empty); + ToOriginalXmlFormat(part, writer); + writer.WriteEndElement(); } } @@ -281,15 +280,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sceneObject.RootPart.ToXml(writer); writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); - lock (sceneObject.Children) + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in sceneObject.Children.Values) - { - if (part.UUID != sceneObject.RootPart.UUID) - { - part.ToXml(writer); - } - } + SceneObjectPart part = parts[i]; + if (part.UUID != sceneObject.RootPart.UUID) + part.ToXml(writer); } writer.WriteEndElement(); // End of OtherParts diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs index 7d9a6a9e99..9244bc3461 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs @@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectGroup dupeSo = scene.SceneGraph.DuplicateObject( part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity); - Assert.That(dupeSo.Children.Count, Is.EqualTo(2)); + Assert.That(dupeSo.Parts.Length, Is.EqualTo(2)); SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1); SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index 60824be683..f57cf98b37 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -81,12 +81,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link."); - Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained children after delink."); - Assert.That(grp1.Children.Count == 2); + Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained children after delink."); + Assert.That(grp1.Parts.Length == 2); if (debugtest) { - m_log.Debug("parts: " + grp1.Children.Count); + m_log.Debug("parts: " + grp1.Parts.Length); m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset); m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset); @@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests if (debugtest) m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset); - Assert.That(grp1.Children.Count, Is.EqualTo(1), "Group 1 still contained part2 after delink."); + Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink."); Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); } @@ -177,22 +177,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests grp3.LinkToGroup(grp4); // At this point we should have 4 parts total in two groups. - Assert.That(grp1.Children.Count == 2, "Group1 children count should be 2"); + Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2"); Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link."); - Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained parts after delink."); - Assert.That(grp3.Children.Count == 2, "Group3 children count should be 2"); + Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained parts after delink."); + Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2"); Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link."); - Assert.That(grp4.Children.Count, Is.EqualTo(0), "Group 4 still contained parts after delink."); + Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink."); if (debugtest) { m_log.Debug("--------After Link-------"); - m_log.Debug("Group1: parts:" + grp1.Children.Count); + m_log.Debug("Group1: parts:" + grp1.Parts.Length); m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset); - - m_log.Debug("Group3: parts:"+grp3.Children.Count); + + m_log.Debug("Group3: parts:" + grp3.Parts.Length); m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation); m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset); m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset); @@ -240,12 +240,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests if (debugtest) { m_log.Debug("--------After De-Link-------"); - m_log.Debug("Group1: parts:" + grp1.Children.Count); + m_log.Debug("Group1: parts:" + grp1.Parts.Length); m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation); m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset); - m_log.Debug("Group3: parts:" + grp3.Children.Count); + m_log.Debug("Group3: parts:" + grp3.Parts.Length); m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation); m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset); m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset); @@ -295,9 +295,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests List storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); Assert.That(storedObjects.Count, Is.EqualTo(1)); - Assert.That(storedObjects[0].Children.Count, Is.EqualTo(2)); - Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); - Assert.That(storedObjects[0].Children.ContainsKey(linkPartUuid)); + Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2)); + Assert.That(storedObjects[0].ContainsPart(rootPartUuid)); + Assert.That(storedObjects[0].ContainsPart(linkPartUuid)); } /// @@ -338,8 +338,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests List storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); Assert.That(storedObjects.Count, Is.EqualTo(1)); - Assert.That(storedObjects[0].Children.Count, Is.EqualTo(1)); - Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); + Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(1)); + Assert.That(storedObjects[0].ContainsPart(rootPartUuid)); } } } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index e3965ce978..65baa5253c 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -121,8 +121,11 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); - foreach (SceneObjectPart part in sceneObject.GetParts()) + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) { + SceneObjectPart part = parts[i]; + // m_log.DebugFormat( // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs index d21b6527f6..7f64ebdbf7 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs @@ -121,19 +121,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement continue; temp = (SceneObjectGroup) currObj; - lock (temp.Children) + if (m_CMEntityHash.ContainsKey(temp.UUID)) { - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach (SceneObjectPart part in temp.Children.Values) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach (SceneObjectPart part in temp.Children.Values) + foreach (SceneObjectPart part in temp.Parts) + if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) missingList.Add(part); - } + } + else //Entire group is missing from revision. (and is a new part in region) + { + foreach (SceneObjectPart part in temp.Parts) + missingList.Add(part); } } return missingList; diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs index 0b02a9fd53..3a6996ef9b 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs @@ -167,11 +167,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) { // Deal with new parts not revisioned that have been deleted. - lock (group.Children) + SceneObjectPart[] parts = group.Parts; + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in group.Children.Values) - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); + if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID)) + m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID); } } @@ -210,12 +210,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement { temp = SceneObjectSerializer.FromXml2Format(xml); temp.SetScene(scene); - - lock (temp.Children) - { - foreach (SceneObjectPart part in temp.Children.Values) - part.RegionHandle = scene.RegionInfo.RegionHandle; - } + + SceneObjectPart[] parts = temp.Parts; + for (int i = 0; i < parts.Length; i++) + parts[i].RegionHandle = scene.RegionInfo.RegionHandle; ReplacementList.Add(temp.UUID, (EntityBase)temp); } @@ -346,17 +344,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement System.Collections.ArrayList auraList = new System.Collections.ArrayList(); if (group == null) return null; - - lock (group.Children) + + SceneObjectPart[] parts = group.Parts; + for (int i = 0; i < parts.Length; i++) { - foreach (SceneObjectPart part in group.Children.Values) + SceneObjectPart part = parts[i]; + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) { - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale); + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); + auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); } } diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs index f75f40a109..3807ccda47 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs @@ -186,12 +186,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); // Deal with new parts not revisioned that have been deleted. - lock (group.Children) - { - foreach (SceneObjectPart part in group.Children.Values) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } + foreach (SceneObjectPart part in group.Parts) + if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) + ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); } public void SendMetaEntitiesToNewClient(IClientAPI client) diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs index 49d20e10f8..0248f368f2 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs @@ -132,33 +132,30 @@ namespace OpenSim.Region.OptionalModules.ContentManagement // if group is not contained in scene's list if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) { - lock (m_UnchangedEntity.Children) + foreach (SceneObjectPart part in m_UnchangedEntity.Parts) { - foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) + // if scene list no longer contains this part, display translucent part and mark with red aura + if (!ContainsKey(sceneEntityList, part.UUID)) { - // if scene list no longer contains this part, display translucent part and mark with red aura - if (!ContainsKey(sceneEntityList, part.UUID)) + // if already displaying a red aura over part, make sure its red + if (m_AuraEntities.ContainsKey(part.UUID)) { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254,0,0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); + m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale); } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id + else + { + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + part.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(254, 0, 0), + part.Scale + ); + m_AuraEntities.Add(part.UUID, auraGroup); + } + SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); + SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); } + // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id } // a deleted part has no where to point a beam particle system, @@ -183,11 +180,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement /// public bool HasChildPrim(UUID uuid) { - lock (m_UnchangedEntity.Children) - if (m_UnchangedEntity.Children.ContainsKey(uuid)) - return true; - - return false; + return m_UnchangedEntity.ContainsPart(uuid); } /// @@ -195,12 +188,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement /// public bool HasChildPrim(uint localID) { - lock (m_UnchangedEntity.Children) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) - if (part.LocalId == localID) - return true; - } + foreach (SceneObjectPart part in m_UnchangedEntity.Parts) + if (part.LocalId == localID) + return true; return false; } @@ -237,72 +227,37 @@ namespace OpenSim.Region.OptionalModules.ContentManagement // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user // had originally saved. // m_Entity will NOT necessarily be the same entity as the user had saved. - lock (m_UnchangedEntity.Children) + foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts) { - foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) + //This is the part that we use to show changes. + metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); + if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID)) { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) + sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID); + differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); + if (differences != Diff.NONE) + metaEntityPart.Text = "CHANGE: " + differences.ToString(); + if (differences != 0) { - sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences&Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new Vector3(0,0,254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,0,254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part + // Root Part that has been modified + if ((differences & Diff.POSITION) > 0) { + // If the position of any part has changed, make sure the RootPart of the + // meta entity is pointing with a beam particle system if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) { m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); + BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, + m_UnchangedEntity.RootPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + sceneEntityPart, + new Vector3(0, 0, 254) + ); + m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) { m_AuraEntities[UnchangedPart.UUID].HideFromAll(); @@ -311,14 +266,46 @@ namespace OpenSim.Region.OptionalModules.ContentManagement AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, UnchangedPart.GetWorldPosition(), MetaEntity.TRANSLUCENT, - new Vector3(254,0,0), + new Vector3(0, 0, 254), UnchangedPart.Scale ); m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - + DiffersFromSceneGroup = true; } + else // no differences between scene part and meta part + { + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + SetPartTransparency(metaEntityPart, MetaEntity.NONE); + } + } + else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. + { + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + UnchangedPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(254, 0, 0), + UnchangedPart.Scale + ); + m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); + SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); + + DiffersFromSceneGroup = true; } } diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs index d7838c56f0..c7b1ed79cc 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -98,10 +98,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement #region Public Properties - public Dictionary Children + public SceneObjectPart[] Parts { - get { return m_Entity.Children; } - set { m_Entity.Children = value; } + get { return m_Entity.Parts; } } public uint LocalId @@ -150,19 +149,17 @@ namespace OpenSim.Region.OptionalModules.ContentManagement { //make new uuids Dictionary parts = new Dictionary(); - - lock (m_Entity.Children) + + foreach (SceneObjectPart part in m_Entity.Parts) { - foreach (SceneObjectPart part in m_Entity.Children.Values) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - //finalize - m_Entity.RootPart.PhysActor = null; - m_Entity.Children = parts; + part.ResetIDs(part.LinkNum); + parts.Add(part.UUID, part); } + + //finalize + m_Entity.RootPart.PhysActor = null; + foreach (SceneObjectPart part in parts.Values) + m_Entity.AddPart(part); } #endregion Protected Methods @@ -177,11 +174,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement //This deletes the group without removing from any databases. //This is important because we are not IN any database. //m_Entity.FakeDeleteGroup(); - lock (m_Entity.Children) - { - foreach (SceneObjectPart part in m_Entity.Children.Values) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); - } + foreach (SceneObjectPart part in m_Entity.Parts) + client.SendKillObject(m_Entity.RegionHandle, part.LocalId); } /// @@ -189,15 +183,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement /// public virtual void HideFromAll() { - lock (m_Entity.Children) + foreach (SceneObjectPart part in m_Entity.Parts) { - foreach (SceneObjectPart part in m_Entity.Children.Values) - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } - ); - } + m_Entity.Scene.ForEachClient( + delegate(IClientAPI controller) + { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } + ); } } diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 59ad9d87a8..faed522899 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -193,11 +193,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule int i = 0; - List partList = null; - lock (my.ParentGroup.Children) - partList = new List(my.ParentGroup.Children.Values); - - foreach (SceneObjectPart part in partList) + foreach (SceneObjectPart part in my.ParentGroup.Parts) { rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0692fdbe47..01c026ee93 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -236,8 +236,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.LINK_SET: if (m_host.ParentGroup != null) { - lock (m_host.ParentGroup.Children) - return new List(m_host.ParentGroup.Children.Values); + return new List(m_host.ParentGroup.Parts); } return ret; @@ -254,8 +253,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentGroup == null) return new List(); - lock (m_host.ParentGroup.Children) - ret = new List(m_host.ParentGroup.Children.Values); + ret = new List(m_host.ParentGroup.Parts); if (ret.Contains(m_host)) ret.Remove(m_host); @@ -265,8 +263,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentGroup == null) return new List(); - lock (m_host.ParentGroup.Children) - ret = new List(m_host.ParentGroup.Children.Values); + ret = new List(m_host.ParentGroup.Parts); if (ret.Contains(m_host.ParentGroup.RootPart)) ret.Remove(m_host.ParentGroup.RootPart); @@ -1187,16 +1184,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (group == null) return; bool allow = true; - - lock (group.Children) + + foreach (SceneObjectPart part in group.Parts) { - foreach (SceneObjectPart part in group.Children.Values) + if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) { - if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) - { - allow = false; - break; - } + allow = false; + break; } } @@ -3617,18 +3611,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_THIS: - lock (parentPrim.Children) + foreach (SceneObjectPart part in parentPrim.Parts) { - foreach (SceneObjectPart part in parentPrim.Children.Values) + if (part.UUID != m_host.UUID) { - if (part.UUID != m_host.UUID) - { - childPrim = part; - break; - } + childPrim = part; + break; } - break; } + break; default: childPrim = parentPrim.GetLinkNumPart(linknum); if (childPrim.UUID == m_host.UUID) @@ -3639,30 +3630,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (linknum == ScriptBaseClass.LINK_ROOT) { // Restructuring Multiple Prims. - lock (parentPrim.Children) + List parts = new List(parentPrim.Parts); + parts.Remove(parentPrim.RootPart); + foreach (SceneObjectPart part in parts) { - List parts = new List(parentPrim.Children.Values); - parts.Remove(parentPrim.RootPart); + parentPrim.DelinkFromGroup(part.LocalId, true); + } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); + parentPrim.TriggerScriptChangedEvent(Changed.LINK); + + if (parts.Count > 0) + { + SceneObjectPart newRoot = parts[0]; + parts.Remove(newRoot); foreach (SceneObjectPart part in parts) { - parentPrim.DelinkFromGroup(part.LocalId, true); - } - parentPrim.HasGroupChanged = true; - parentPrim.ScheduleGroupForFullUpdate(); - parentPrim.TriggerScriptChangedEvent(Changed.LINK); - - if (parts.Count > 0) - { - SceneObjectPart newRoot = parts[0]; - parts.Remove(newRoot); - foreach (SceneObjectPart part in parts) - { - part.UpdateFlag = 0; - newRoot.ParentGroup.LinkToGroup(part.ParentGroup); - } - newRoot.ParentGroup.HasGroupChanged = true; - newRoot.ParentGroup.ScheduleGroupForFullUpdate(); + part.UpdateFlag = 0; + newRoot.ParentGroup.LinkToGroup(part.ParentGroup); } + newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } else @@ -3684,19 +3672,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (parentPrim.RootPart.AttachmentPoint != 0) return; // Fail silently if attached - lock (parentPrim.Children) + List parts = new List(parentPrim.Parts); + parts.Remove(parentPrim.RootPart); + + foreach (SceneObjectPart part in parts) { - List parts = new List(parentPrim.Children.Values); - parts.Remove(parentPrim.RootPart); - - foreach (SceneObjectPart part in parts) - { - parentPrim.DelinkFromGroup(part.LocalId, true); - parentPrim.TriggerScriptChangedEvent(Changed.LINK); - } - parentPrim.HasGroupChanged = true; - parentPrim.ScheduleGroupForFullUpdate(); + parentPrim.DelinkFromGroup(part.LocalId, true); + parentPrim.TriggerScriptChangedEvent(Changed.LINK); } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); } public LSL_String llGetLinkKey(int linknum) diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 41501f24dd..3575889d3c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -209,15 +209,12 @@ namespace OpenSim.Region.ScriptEngine.Shared else Type = 0x02; // Passive - lock (part.ParentGroup.Children) + foreach (SceneObjectPart p in part.ParentGroup.Parts) { - foreach (SceneObjectPart p in part.ParentGroup.Children.Values) + if (p.Inventory.ContainsScripts()) { - if (p.Inventory.ContainsScripts()) - { - Type |= 0x08; // Scripted - break; - } + Type |= 0x08; // Scripted + break; } } diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs index de6e815a9b..2e5020b043 100644 --- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs @@ -163,7 +163,7 @@ namespace OpenSim.Data.Null // We can't simply store groups here because on delinking, OpenSim will not update the original group // directly. Rather, the newly delinked parts will be updated to be in their own scene object group // Therefore, we need to store parts rather than groups. - foreach (SceneObjectPart prim in obj.Children.Values) + foreach (SceneObjectPart prim in obj.Parts) { m_log.DebugFormat( "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}", From b49cb3355f3e5d2f3fa131ed3a5b0020cce503e2 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 16 Sep 2010 17:57:00 -0700 Subject: [PATCH 7/8] Fixed a regression in SOG.Copy() --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c984afc5fc..994b9e3243 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1378,7 +1378,7 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); dupe.m_isBackedUp = false; - dupe.m_parts.Clear(); + dupe.m_parts = new MapAndArray(); // Warning, The following code related to previousAttachmentStatus is needed so that clones of // attachments do not bordercross while they're being duplicated. This is hacktastic! From 7762301cea99215df4068cca71b78335df5a4a40 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 17 Sep 2010 01:50:48 +0200 Subject: [PATCH 8/8] Revert "* Changed 11 calls for session info to the more optimized API method" This reverts commit 5dc9ea2f2487804d788b4b80d40d91bd792de4c2. Also makes online indicators and IM more robust --- .../Avatar/Friends/FriendsModule.cs | 103 ++++++++++++------ .../InstantMessage/MessageTransferModule.cs | 13 ++- .../Shared/Api/Implementation/LSL_Api.cs | 26 ++++- .../Connectors/SimianGrid/SimianProfiles.cs | 4 +- 4 files changed, 109 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4e4eee9386..7a21d5e6b2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -317,7 +317,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends continue; UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); - PresenceInfo presence = PresenceService.GetAgent(fromAgentID); + + PresenceInfo presence = null; + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); + if (presences != null && presences.Length > 0) + presence = presences[0]; + if (presence != null) + im.offline = 0; im.fromAgentID = fromAgentID.Guid; im.fromAgentName = account.FirstName + " " + account.LastName; @@ -430,13 +436,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return; // The friend is not here [as root]. Let's forward. - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null && friendSession.RegionID != UUID.Zero) // let's guard against sessions-gone-bad with the RegionID check + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } + + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } } + + // Friend is not online. Ignore. } else { @@ -477,11 +496,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return; // The prospective friend is not here [as root]. Let's forward. - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); + } } // If the prospective friend is not online, he'll get the message upon login. } @@ -508,12 +531,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // The friend is not here - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); - client.SendAgentOnline(new UUID[] { friendID }); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); + client.SendAgentOnline(new UUID[] { friendID }); + } } } @@ -532,14 +559,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalFriendshipDenied(agentID, client.Name, friendID)) return; - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - if (region != null) - m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); - else - m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + if (region != null) + m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + else + m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); + } } } @@ -561,11 +592,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalFriendshipTerminated(exfriendID)) return; - PresenceInfo friendSession = PresenceService.GetAgent(exfriendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); + } } } @@ -604,13 +639,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalGrantRights(requester, target, myFlags, rights)) return; - PresenceInfo friendSession = PresenceService.GetAgent(target); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - // TODO: You might want to send the delta to save the lookup - // on the other end!! - m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + // TODO: You might want to send the delta to save the lookup + // on the other end!! + m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + } } } } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 43bbf0d5ad..9b1222b627 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -498,7 +498,18 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (lookupAgent) { // Non-cached user agent lookup. - upd = PresenceService.GetAgent(toAgentID); + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) + { + upd = p; + break; + } + } + } if (upd != null) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 01c026ee93..621d429c4a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3956,7 +3956,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } - pinfo = World.PresenceService.GetAgent(uuid); + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + { + foreach (PresenceInfo p in pinfos) + { + if (p.RegionID != UUID.Zero) + { + pinfo = p; + } + } + } ce = new UserInfoCacheEntry(); ce.time = Util.EnvironmentTickCount(); @@ -3974,7 +3984,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) { - pinfo = World.PresenceService.GetAgent(uuid); + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + { + foreach (PresenceInfo p in pinfos) + { + if (p.RegionID != UUID.Zero) + { + pinfo = p; + } + } + } + else + pinfo = null; ce.time = Util.EnvironmentTickCount(); ce.pinfo = pinfo; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index b7e8538824..0ef4974f79 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -291,8 +291,8 @@ namespace OpenSim.Services.Connectors.SimianGrid // Check if the user is online if (client.Scene is Scene) { - OpenSim.Services.Interfaces.PresenceInfo presence = ((Scene)client.Scene).PresenceService.GetAgent(avatarID); - if (presence != null) + OpenSim.Services.Interfaces.PresenceInfo[] presences = ((Scene)client.Scene).PresenceService.GetAgents(new string[] { avatarID.ToString() }); + if (presences != null && presences.Length > 0) flags |= ProfileFlags.Online; }