aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Data/MSSQL/MSSQLSimulationData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs2
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs2
-rw-r--r--OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs2
-rw-r--r--OpenSim/Data/Tests/RegionTests.cs14
-rw-r--r--OpenSim/Framework/MapAndArray.cs188
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs7
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs8
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs55
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1460
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs5
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs19
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs35
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs9
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs169
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs45
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs56
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs11
-rw-r--r--OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs6
36 files changed, 1034 insertions, 1275 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 8eae0a2..1da52b4 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -241,7 +241,7 @@ namespace OpenSim.Data.MSSQL
241 /// <param name="regionUUID"></param> 241 /// <param name="regionUUID"></param>
242 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 242 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
243 { 243 {
244 _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); 244 _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length);
245 245
246 using (SqlConnection conn = new SqlConnection(m_connectionString)) 246 using (SqlConnection conn = new SqlConnection(m_connectionString))
247 { 247 {
@@ -250,7 +250,7 @@ namespace OpenSim.Data.MSSQL
250 250
251 try 251 try
252 { 252 {
253 foreach (SceneObjectPart sceneObjectPart in obj.Children.Values) 253 foreach (SceneObjectPart sceneObjectPart in obj.Parts)
254 { 254 {
255 //Update prim 255 //Update prim
256 using (SqlCommand sqlCommand = conn.CreateCommand()) 256 using (SqlCommand sqlCommand = conn.CreateCommand())
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 87f6d07..3450e2f 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -144,7 +144,7 @@ namespace OpenSim.Data.MySQL
144 dbcon.Open(); 144 dbcon.Open();
145 MySqlCommand cmd = dbcon.CreateCommand(); 145 MySqlCommand cmd = dbcon.CreateCommand();
146 146
147 foreach (SceneObjectPart prim in obj.Children.Values) 147 foreach (SceneObjectPart prim in obj.Parts)
148 { 148 {
149 cmd.Parameters.Clear(); 149 cmd.Parameters.Clear();
150 150
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 3e9bc3f..ebe6da8 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -368,7 +368,7 @@ namespace OpenSim.Data.SQLite
368 368
369 lock (ds) 369 lock (ds)
370 { 370 {
371 foreach (SceneObjectPart prim in obj.Children.Values) 371 foreach (SceneObjectPart prim in obj.Parts)
372 { 372 {
373// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); 373// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
374 addPrim(prim, obj.UUID, regionUUID); 374 addPrim(prim, obj.UUID, regionUUID);
diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
index 2dde926..ce18a42 100644
--- a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
@@ -335,7 +335,7 @@ namespace OpenSim.Data.SQLiteLegacy
335 335
336 lock (ds) 336 lock (ds)
337 { 337 {
338 foreach (SceneObjectPart prim in obj.Children.Values) 338 foreach (SceneObjectPart prim in obj.Parts)
339 { 339 {
340// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); 340// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
341 addPrim(prim, obj.UUID, regionUUID); 341 addPrim(prim, obj.UUID, regionUUID);
diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs
index a081462..23d498d 100644
--- a/OpenSim/Data/Tests/RegionTests.cs
+++ b/OpenSim/Data/Tests/RegionTests.cs
@@ -232,15 +232,15 @@ namespace OpenSim.Data.Tests
232 sog.AddPart(p2); 232 sog.AddPart(p2);
233 sog.AddPart(p3); 233 sog.AddPart(p3);
234 234
235 SceneObjectPart[] parts = sog.GetParts(); 235 SceneObjectPart[] parts = sog.Parts;
236 Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); 236 Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))");
237 237
238 db.StoreObject(sog, newregion); 238 db.StoreObject(sog, newregion);
239 List<SceneObjectGroup> sogs = db.LoadObjects(newregion); 239 List<SceneObjectGroup> sogs = db.LoadObjects(newregion);
240 Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); 240 Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))");
241 SceneObjectGroup newsog = sogs[0]; 241 SceneObjectGroup newsog = sogs[0];
242 242
243 SceneObjectPart[] newparts = newsog.GetParts(); 243 SceneObjectPart[] newparts = newsog.Parts;
244 Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); 244 Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))");
245 245
246 Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))"); 246 Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))");
@@ -560,7 +560,7 @@ namespace OpenSim.Data.Tests
560 } 560 }
561 561
562 SceneObjectGroup retsog = FindSOG("Test SOG", region4); 562 SceneObjectGroup retsog = FindSOG("Test SOG", region4);
563 SceneObjectPart[] parts = retsog.GetParts(); 563 SceneObjectPart[] parts = retsog.Parts;
564 for (int i=0;i<30;i++) 564 for (int i=0;i<30;i++)
565 { 565 {
566 SceneObjectPart cursop = mydic[parts[i].UUID]; 566 SceneObjectPart cursop = mydic[parts[i].UUID];
@@ -607,7 +607,7 @@ namespace OpenSim.Data.Tests
607 sog.AddPart(p2); 607 sog.AddPart(p2);
608 sog.AddPart(p3); 608 sog.AddPart(p3);
609 609
610 SceneObjectPart[] parts = sog.GetParts(); 610 SceneObjectPart[] parts = sog.Parts;
611 Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); 611 Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))");
612 612
613 db.StoreObject(sog, newregion); 613 db.StoreObject(sog, newregion);
@@ -615,7 +615,7 @@ namespace OpenSim.Data.Tests
615 Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); 615 Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))");
616 SceneObjectGroup newsog = sogs[0]; 616 SceneObjectGroup newsog = sogs[0];
617 617
618 SceneObjectPart[] newparts = newsog.GetParts(); 618 SceneObjectPart[] newparts = newsog.Parts;
619 Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); 619 Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))");
620 620
621 Assert.That(newsog, Constraints.PropertyCompareConstraint(sog) 621 Assert.That(newsog, Constraints.PropertyCompareConstraint(sog)
@@ -625,7 +625,7 @@ namespace OpenSim.Data.Tests
625 .IgnoreProperty(x=>x.RegionHandle) 625 .IgnoreProperty(x=>x.RegionHandle)
626 .IgnoreProperty(x=>x.RegionUUID) 626 .IgnoreProperty(x=>x.RegionUUID)
627 .IgnoreProperty(x=>x.Scene) 627 .IgnoreProperty(x=>x.Scene)
628 .IgnoreProperty(x=>x.Children) 628 .IgnoreProperty(x=>x.Parts)
629 .IgnoreProperty(x=>x.PassCollision) 629 .IgnoreProperty(x=>x.PassCollision)
630 .IgnoreProperty(x=>x.RootPart)); 630 .IgnoreProperty(x=>x.RootPart));
631 } 631 }
diff --git a/OpenSim/Framework/MapAndArray.cs b/OpenSim/Framework/MapAndArray.cs
new file mode 100644
index 0000000..bbe6a9e
--- /dev/null
+++ b/OpenSim/Framework/MapAndArray.cs
@@ -0,0 +1,188 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// Stores two synchronized collections: a mutable dictionary and an
35 /// immutable array. Slower inserts/removes than a normal dictionary,
36 /// but provides safe iteration while maintaining fast hash lookups
37 /// </summary>
38 /// <typeparam name="TKey">Key type to use for hash lookups</typeparam>
39 /// <typeparam name="TValue">Value type to store</typeparam>
40 public sealed class MapAndArray<TKey, TValue>
41 {
42 private Dictionary<TKey, TValue> m_dict;
43 private TValue[] m_array;
44 private object m_syncRoot = new object();
45
46 /// <summary>Number of values currently stored in the collection</summary>
47 public int Count { get { return m_array.Length; } }
48 /// <summary>NOTE: This collection is thread safe. You do not need to
49 /// acquire a lock to add, remove, or enumerate entries. This
50 /// synchronization object should only be locked for larger
51 /// transactions</summary>
52 public object SyncRoot { get { return m_syncRoot; } }
53
54 /// <summary>
55 /// Constructor
56 /// </summary>
57 public MapAndArray()
58 {
59 m_dict = new Dictionary<TKey, TValue>();
60 m_array = new TValue[0];
61 }
62
63 /// <summary>
64 /// Constructor
65 /// </summary>
66 /// <param name="capacity">Initial capacity of the dictionary</param>
67 public MapAndArray(int capacity)
68 {
69 m_dict = new Dictionary<TKey, TValue>(capacity);
70 m_array = new TValue[0];
71 }
72
73 /// <summary>
74 /// Adds a key/value pair to the collection, or updates an existing key
75 /// with a new value
76 /// </summary>
77 /// <param name="key">Key to add or update</param>
78 /// <param name="value">Value to add</param>
79 /// <returns>True if a new key was added, false if an existing key was
80 /// updated</returns>
81 public bool AddOrReplace(TKey key, TValue value)
82 {
83 lock (m_syncRoot)
84 {
85 bool containedKey = m_dict.ContainsKey(key);
86
87 m_dict[key] = value;
88 CreateArray();
89
90 return !containedKey;
91 }
92 }
93
94 /// <summary>
95 /// Adds a key/value pair to the collection. This will throw an
96 /// exception if the key is already present in the collection
97 /// </summary>
98 /// <param name="key">Key to add or update</param>
99 /// <param name="value">Value to add</param>
100 /// <returns>Index of the inserted item</returns>
101 public int Add(TKey key, TValue value)
102 {
103 lock (m_syncRoot)
104 {
105 m_dict.Add(key, value);
106 CreateArray();
107 return m_array.Length;
108 }
109 }
110
111 /// <summary>
112 /// Removes a key/value pair from the collection
113 /// </summary>
114 /// <param name="key">Key to remove</param>
115 /// <returns>True if the key was found and removed, otherwise false</returns>
116 public bool Remove(TKey key)
117 {
118 lock (m_syncRoot)
119 {
120 bool removed = m_dict.Remove(key);
121 CreateArray();
122
123 return removed;
124 }
125 }
126
127 /// <summary>
128 /// Determines whether the collections contains a specified key
129 /// </summary>
130 /// <param name="key">Key to search for</param>
131 /// <returns>True if the key was found, otherwise false</returns>
132 public bool ContainsKey(TKey key)
133 {
134 return m_dict.ContainsKey(key);
135 }
136
137 /// <summary>
138 /// Gets the value associated with the specified key
139 /// </summary>
140 /// <param name="key">Key of the value to get</param>
141 /// <param name="value">Will contain the value associated with the
142 /// given key if the key is found. If the key is not found it will
143 /// contain the default value for the type of the value parameter</param>
144 /// <returns>True if the key was found and a value was retrieved,
145 /// otherwise false</returns>
146 public bool TryGetValue(TKey key, out TValue value)
147 {
148 lock (m_syncRoot)
149 return m_dict.TryGetValue(key, out value);
150 }
151
152 /// <summary>
153 /// Clears all key/value pairs from the collection
154 /// </summary>
155 public void Clear()
156 {
157 lock (m_syncRoot)
158 {
159 m_dict = new Dictionary<TKey, TValue>();
160 m_array = new TValue[0];
161 }
162 }
163
164 /// <summary>
165 /// Gets a reference to the immutable array of values stored in this
166 /// collection. This array is thread safe for iteration
167 /// </summary>
168 /// <returns>A thread safe reference ton an array of all of the stored
169 /// values</returns>
170 public TValue[] GetArray()
171 {
172 return m_array;
173 }
174
175 private void CreateArray()
176 {
177 // Rebuild the array from the dictionary. This method must be
178 // called from inside a lock
179 TValue[] array = new TValue[m_dict.Count];
180 int i = 0;
181
182 foreach (TValue value in m_dict.Values)
183 array[i++] = value;
184
185 m_array = array;
186 }
187 }
188}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 0f1a1ca..dca1346 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -1533,7 +1533,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1533 lock (m_entityUpdates.SyncRoot) 1533 lock (m_entityUpdates.SyncRoot)
1534 { 1534 {
1535 m_killRecord.Add(localID); 1535 m_killRecord.Add(localID);
1536 OutPacket(kill, ThrottleOutPacketType.State); 1536
1537 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1538 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1539 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1540 // scene objects in a viewer until that viewer is relogged in.
1541 OutPacket(kill, ThrottleOutPacketType.Task);
1537 } 1542 }
1538 } 1543 }
1539 } 1544 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index eebbfa5..a4738ff 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -420,8 +420,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
420 420
421 /// <summary> 421 /// <summary>
422 /// Loops through all of the packet queues for this client and tries to send 422 /// Loops through all of the packet queues for this client and tries to send
423 /// any outgoing packets, obeying the throttling bucket limits 423 /// an outgoing packet from each, obeying the throttling bucket limits
424 /// </summary> 424 /// </summary>
425 ///
426 /// Packet queues are inspected in ascending numerical order starting from 0. Therefore, queues with a lower
427 /// ThrottleOutPacketType number will see their packet get sent first (e.g. if both Land and Wind queues have
428 /// packets, then the packet at the front of the Land queue will be sent before the packet at the front of the
429 /// wind queue).
430 ///
425 /// <remarks>This function is only called from a synchronous loop in the 431 /// <remarks>This function is only called from a synchronous loop in the
426 /// UDPServer so we don't need to bother making this thread safe</remarks> 432 /// UDPServer so we don't need to bother making this thread safe</remarks>
427 /// <returns>True if any packets were sent, otherwise false</returns> 433 /// <returns>True if any packets were sent, otherwise false</returns>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 5aeca83..e2cda6d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -500,6 +500,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
500 // FIXME: Implement? 500 // FIXME: Implement?
501 } 501 }
502 502
503 /// <summary>
504 /// Actually send a packet to a client.
505 /// </summary>
506 /// <param name="outgoingPacket"></param>
503 internal void SendPacketFinal(OutgoingPacket outgoingPacket) 507 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
504 { 508 {
505 UDPPacketBuffer buffer = outgoingPacket.Buffer; 509 UDPPacketBuffer buffer = outgoingPacket.Buffer;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 7c95658..6f7256e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -586,13 +586,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
586 so.RootPart.AttachedAvatar = avatar.UUID; 586 so.RootPart.AttachedAvatar = avatar.UUID;
587 587
588 //Anakin Lohner bug #3839 588 //Anakin Lohner bug #3839
589 lock (so.Children) 589 SceneObjectPart[] parts = so.Parts;
590 { 590 for (int i = 0; i < parts.Length; i++)
591 foreach (SceneObjectPart p in so.Children.Values) 591 parts[i].AttachedAvatar = avatar.UUID;
592 {
593 p.AttachedAvatar = avatar.UUID;
594 }
595 }
596 592
597 if (so.RootPart.PhysActor != null) 593 if (so.RootPart.PhysActor != null)
598 { 594 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index a2ba498..42e3359 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -544,7 +544,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
544 if (!attachment) 544 if (!attachment)
545 { 545 {
546 group.RootPart.CreateSelected = true; 546 group.RootPart.CreateSelected = true;
547 foreach (SceneObjectPart child in group.Children.Values) 547 foreach (SceneObjectPart child in group.Parts)
548 child.CreateSelected = true; 548 child.CreateSelected = true;
549 } 549 }
550 550
@@ -629,10 +629,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
629 rootPart.Name = item.Name; 629 rootPart.Name = item.Name;
630 rootPart.Description = item.Description; 630 rootPart.Description = item.Description;
631 631
632 List<SceneObjectPart> partList = null;
633 lock (group.Children)
634 partList = new List<SceneObjectPart>(group.Children.Values);
635
636 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 632 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
637 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) 633 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
638 { 634 {
@@ -642,7 +638,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
642 638
643 if (m_Scene.Permissions.PropagatePermissions()) 639 if (m_Scene.Permissions.PropagatePermissions())
644 { 640 {
645 foreach (SceneObjectPart part in partList) 641 foreach (SceneObjectPart part in group.Parts)
646 { 642 {
647 part.EveryoneMask = item.EveryOnePermissions; 643 part.EveryoneMask = item.EveryOnePermissions;
648 part.NextOwnerMask = item.NextPermissions; 644 part.NextOwnerMask = item.NextPermissions;
@@ -656,7 +652,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
656 { 652 {
657 m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 8"); 653 m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 8");
658 } 654 }
659 foreach (SceneObjectPart part in partList) 655
656 foreach (SceneObjectPart part in group.Parts)
660 { 657 {
661 if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) 658 if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
662 { 659 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index e51f118..4af7a1b 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
243 // to the same scene (when this is possible). 243 // to the same scene (when this is possible).
244 sceneObject.ResetIDs(); 244 sceneObject.ResetIDs();
245 245
246 List<SceneObjectPart> partList = null; 246 foreach (SceneObjectPart part in sceneObject.Parts)
247 lock (sceneObject.Children)
248 partList = new List<SceneObjectPart>(sceneObject.Children.Values);
249
250 foreach (SceneObjectPart part in partList)
251 { 247 {
252 if (!ResolveUserUuid(part.CreatorID)) 248 if (!ResolveUserUuid(part.CreatorID))
253 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 249 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 db50339..d91c36c 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
128 group.SetOwnerId(remoteClient.AgentId); 128 group.SetOwnerId(remoteClient.AgentId);
129 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId); 129 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);
130 130
131 List<SceneObjectPart> partList = null;
132
133 lock (group.Children)
134 partList = new List<SceneObjectPart>(group.Children.Values);
135
136 if (m_scene.Permissions.PropagatePermissions()) 131 if (m_scene.Permissions.PropagatePermissions())
137 { 132 {
138 foreach (SceneObjectPart child in partList) 133 foreach (SceneObjectPart child in group.Parts)
139 { 134 {
140 child.Inventory.ChangeInventoryOwner(remoteClient.AgentId); 135 child.Inventory.ChangeInventoryOwner(remoteClient.AgentId);
141 child.TriggerScriptChangedEvent(Changed.OWNER); 136 child.TriggerScriptChangedEvent(Changed.OWNER);
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
index 1bd1371..c83ac85 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
229 Color mapdotspot = Color.Gray; // Default color when prim color is white 229 Color mapdotspot = Color.Gray; // Default color when prim color is white
230 230
231 // Loop over prim in group 231 // Loop over prim in group
232 List<SceneObjectPart> partList = null; 232 foreach (SceneObjectPart part in mapdot.Parts)
233 lock (mapdot.Children)
234 partList = new List<SceneObjectPart>(mapdot.Children.Values);
235
236 foreach (SceneObjectPart part in partList)
237 { 233 {
238 if (part == null) 234 if (part == null)
239 continue; 235 continue;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 867fb10..ac82fda 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2064,9 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes
2064 sog.SetGroup(groupID, remoteClient); 2064 sog.SetGroup(groupID, remoteClient);
2065 sog.ScheduleGroupForFullUpdate(); 2065 sog.ScheduleGroupForFullUpdate();
2066 2066
2067 List<SceneObjectPart> partList = null; 2067 SceneObjectPart[] partList = sog.Parts;
2068 lock (sog.Children)
2069 partList = new List<SceneObjectPart>(sog.Children.Values);
2070 2068
2071 foreach (SceneObjectPart child in partList) 2069 foreach (SceneObjectPart child in partList)
2072 child.Inventory.ChangeInventoryOwner(ownerID); 2070 child.Inventory.ChangeInventoryOwner(ownerID);
@@ -2079,9 +2077,7 @@ namespace OpenSim.Region.Framework.Scenes
2079 if (sog.GroupID != groupID) 2077 if (sog.GroupID != groupID)
2080 continue; 2078 continue;
2081 2079
2082 List<SceneObjectPart> partList = null; 2080 SceneObjectPart[] partList = sog.Parts;
2083 lock (sog.Children)
2084 partList = new List<SceneObjectPart>(sog.Children.Values);
2085 2081
2086 foreach (SceneObjectPart child in partList) 2082 foreach (SceneObjectPart child in partList)
2087 { 2083 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 7788e43..4d97db7 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
161 bool foundPrim = false; 161 bool foundPrim = false;
162 162
163 SceneObjectGroup sog = ent as SceneObjectGroup; 163 SceneObjectGroup sog = ent as SceneObjectGroup;
164
165 List<SceneObjectPart> partList = null;
166 lock (sog.Children)
167 partList = new List<SceneObjectPart>(sog.Children.Values);
168 164
165 SceneObjectPart[] partList = sog.Parts;
169 foreach (SceneObjectPart part in partList) 166 foreach (SceneObjectPart part in partList)
170 { 167 {
171 if (part.LocalId == primLocalID) 168 if (part.LocalId == primLocalID)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 33e3e5d..240d33c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1819,7 +1819,7 @@ namespace OpenSim.Region.Framework.Scenes
1819 { 1819 {
1820 m_log.ErrorFormat( 1820 m_log.ErrorFormat(
1821 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", 1821 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1822 group.Children == null ? 0 : group.PrimCount); 1822 group.Parts == null ? 0 : group.PrimCount);
1823 } 1823 }
1824 1824
1825 AddRestoredSceneObject(group, true, true); 1825 AddRestoredSceneObject(group, true, true);
@@ -2160,9 +2160,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 group.RemoveScriptInstances(true); 2160 group.RemoveScriptInstances(true);
2161 } 2161 }
2162 2162
2163 List<SceneObjectPart> partList = null; 2163 SceneObjectPart[] partList = group.Parts;
2164 lock (group.Children)
2165 partList = new List<SceneObjectPart>(group.Children.Values);
2166 2164
2167 foreach (SceneObjectPart part in partList) 2165 foreach (SceneObjectPart part in partList)
2168 { 2166 {
@@ -2540,11 +2538,9 @@ namespace OpenSim.Region.Framework.Scenes
2540 2538
2541 // Force allocation of new LocalId 2539 // Force allocation of new LocalId
2542 // 2540 //
2543 lock (sceneObject.Children) 2541 SceneObjectPart[] parts = sceneObject.Parts;
2544 { 2542 for (int i = 0; i < parts.Length; i++)
2545 foreach (SceneObjectPart p in sceneObject.Children.Values) 2543 parts[i].LocalId = 0;
2546 p.LocalId = 0;
2547 }
2548 2544
2549 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2545 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2550 { 2546 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 9c3486e..5ef14bf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -270,7 +270,7 @@ namespace OpenSim.Region.Framework.Scenes
270 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; 270 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
271 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; 271 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
272 272
273 foreach (SceneObjectPart part in sceneObject.Children.Values) 273 foreach (SceneObjectPart part in sceneObject.Parts)
274 { 274 {
275 part.GroupPosition = npos; 275 part.GroupPosition = npos;
276 } 276 }
@@ -370,9 +370,7 @@ namespace OpenSim.Region.Framework.Scenes
370 if (Entities.ContainsKey(sceneObject.UUID)) 370 if (Entities.ContainsKey(sceneObject.UUID))
371 return false; 371 return false;
372 372
373 List<SceneObjectPart> children; 373 SceneObjectPart[] children = sceneObject.Parts;
374 lock (sceneObject.Children)
375 children = new List<SceneObjectPart>(sceneObject.Children.Values);
376 374
377 // Clamp child prim sizes and add child prims to the m_numPrim count 375 // Clamp child prim sizes and add child prims to the m_numPrim count
378 if (m_parentScene.m_clampPrimSize) 376 if (m_parentScene.m_clampPrimSize)
@@ -391,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
391 part.Shape.Scale = scale; 389 part.Shape.Scale = scale;
392 } 390 }
393 } 391 }
394 m_numPrim += children.Count; 392 m_numPrim += children.Length;
395 393
396 sceneObject.AttachToScene(m_parentScene); 394 sceneObject.AttachToScene(m_parentScene);
397 395
@@ -448,15 +446,17 @@ namespace OpenSim.Region.Framework.Scenes
448 446
449 lock (SceneObjectGroupsByFullID) 447 lock (SceneObjectGroupsByFullID)
450 { 448 {
451 foreach (SceneObjectPart part in grp.Children.Values) 449 SceneObjectPart[] parts = grp.Parts;
452 SceneObjectGroupsByFullID.Remove(part.UUID); 450 for (int i = 0; i < parts.Length; i++)
451 SceneObjectGroupsByFullID.Remove(parts[i].UUID);
453 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); 452 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID);
454 } 453 }
455 454
456 lock (SceneObjectGroupsByLocalID) 455 lock (SceneObjectGroupsByLocalID)
457 { 456 {
458 foreach (SceneObjectPart part in grp.Children.Values) 457 SceneObjectPart[] parts = grp.Parts;
459 SceneObjectGroupsByLocalID.Remove(part.LocalId); 458 for (int i = 0; i < parts.Length; i++)
459 SceneObjectGroupsByLocalID.Remove(parts[i].LocalId);
460 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); 460 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId);
461 } 461 }
462 462
@@ -943,11 +943,8 @@ namespace OpenSim.Region.Framework.Scenes
943 943
944 if (sog != null) 944 if (sog != null)
945 { 945 {
946 lock (sog.Children) 946 if (sog.ContainsPart(fullID))
947 { 947 return sog;
948 if (sog.Children.ContainsKey(fullID))
949 return sog;
950 }
951 948
952 lock (SceneObjectGroupsByFullID) 949 lock (SceneObjectGroupsByFullID)
953 SceneObjectGroupsByFullID.Remove(fullID); 950 SceneObjectGroupsByFullID.Remove(fullID);
@@ -1021,7 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes
1021 { 1018 {
1022 if (entity is SceneObjectGroup) 1019 if (entity is SceneObjectGroup)
1023 { 1020 {
1024 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts()) 1021 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
1025 { 1022 {
1026 if (p.Name == name) 1023 if (p.Name == name)
1027 { 1024 {
@@ -1686,14 +1683,8 @@ namespace OpenSim.Region.Framework.Scenes
1686 SceneObjectGroup group = root.ParentGroup; 1683 SceneObjectGroup group = root.ParentGroup;
1687 group.areUpdatesSuspended = true; 1684 group.areUpdatesSuspended = true;
1688 1685
1689 List<SceneObjectPart> newSet = null; 1686 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1690 int numChildren; 1687 int numChildren = newSet.Count;
1691
1692 lock (group.Children)
1693 {
1694 newSet = new List<SceneObjectPart>(group.Children.Values);
1695 numChildren = group.PrimCount;
1696 }
1697 1688
1698 if (numChildren == 1) 1689 if (numChildren == 1)
1699 break; 1690 break;
@@ -1783,16 +1774,13 @@ namespace OpenSim.Region.Framework.Scenes
1783 if (ent is SceneObjectGroup) 1774 if (ent is SceneObjectGroup)
1784 { 1775 {
1785 SceneObjectGroup sog = ent as SceneObjectGroup; 1776 SceneObjectGroup sog = ent as SceneObjectGroup;
1786 1777
1787 lock (sog.Children) 1778 foreach (SceneObjectPart part in sog.Parts)
1788 { 1779 {
1789 foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children) 1780 if (part.LocalId == localID)
1790 { 1781 {
1791 if (subent.Value.LocalId == localID) 1782 objid = part.UUID;
1792 { 1783 obj = part;
1793 objid = subent.Key;
1794 obj = subent.Value;
1795 }
1796 } 1784 }
1797 } 1785 }
1798 } 1786 }
@@ -1868,8 +1856,7 @@ namespace OpenSim.Region.Framework.Scenes
1868 copy.SetOwnerId(AgentID); 1856 copy.SetOwnerId(AgentID);
1869 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 1857 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1870 1858
1871 List<SceneObjectPart> partList = 1859 SceneObjectPart[] partList = copy.Parts;
1872 new List<SceneObjectPart>(copy.Children.Values);
1873 1860
1874 if (m_parentScene.Permissions.PropagatePermissions()) 1861 if (m_parentScene.Permissions.PropagatePermissions())
1875 { 1862 {
@@ -1891,7 +1878,7 @@ namespace OpenSim.Region.Framework.Scenes
1891 // think it's selected, so it will never send a deselect... 1878 // think it's selected, so it will never send a deselect...
1892 copy.IsSelected = false; 1879 copy.IsSelected = false;
1893 1880
1894 m_numPrim += copy.Children.Count; 1881 m_numPrim += copy.Parts.Length;
1895 1882
1896 if (rot != Quaternion.Identity) 1883 if (rot != Quaternion.Identity)
1897 { 1884 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index a7003c4..6cc7231 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
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lockPartsForRead(true); 49 SceneObjectPart[] parts = m_parts.GetArray();
50 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); 50 for (int i = 0; i < parts.Length; i++)
51 lockPartsForRead(false); 51 parts[i].Inventory.ForceInventoryPersistence();
52 foreach (SceneObjectPart part in values)
53 {
54 part.Inventory.ForceInventoryPersistence();
55 }
56 } 52 }
57 53
58 /// <summary> 54 /// <summary>
@@ -64,10 +60,9 @@ namespace OpenSim.Region.Framework.Scenes
64 // Don't start scripts if they're turned off in the region! 60 // Don't start scripts if they're turned off in the region!
65 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 61 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
66 { 62 {
67 foreach (SceneObjectPart part in m_parts.Values) 63 SceneObjectPart[] parts = m_parts.GetArray();
68 { 64 for (int i = 0; i < parts.Length; i++)
69 part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); 65 parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
70 }
71 } 66 }
72 } 67 }
73 68
@@ -76,15 +71,9 @@ namespace OpenSim.Region.Framework.Scenes
76 /// </summary> 71 /// </summary>
77 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
78 { 73 {
79 lockPartsForRead(true); 74 SceneObjectPart[] parts = m_parts.GetArray();
80 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); 75 for (int i = 0; i < parts.Length; i++)
81 lockPartsForRead(false); 76 parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
82
83 foreach (SceneObjectPart part in values)
84 {
85 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 }
87
88 } 77 }
89 78
90 /// <summary> 79 /// <summary>
@@ -281,8 +270,11 @@ namespace OpenSim.Region.Framework.Scenes
281 PermissionMask.Transfer) | 7; 270 PermissionMask.Transfer) | 7;
282 271
283 uint ownerMask = 0x7fffffff; 272 uint ownerMask = 0x7fffffff;
284 foreach (SceneObjectPart part in m_parts.Values) 273
274 SceneObjectPart[] parts = m_parts.GetArray();
275 for (int i = 0; i < parts.Length; i++)
285 { 276 {
277 SceneObjectPart part = parts[i];
286 ownerMask &= part.OwnerMask; 278 ownerMask &= part.OwnerMask;
287 perms &= part.Inventory.MaskEffectivePermissions(); 279 perms &= part.Inventory.MaskEffectivePermissions();
288 } 280 }
@@ -310,39 +302,40 @@ namespace OpenSim.Region.Framework.Scenes
310 302
311 public void ApplyNextOwnerPermissions() 303 public void ApplyNextOwnerPermissions()
312 { 304 {
313 foreach (SceneObjectPart part in m_parts.Values) 305 SceneObjectPart[] parts = m_parts.GetArray();
314 { 306 for (int i = 0; i < parts.Length; i++)
315 part.ApplyNextOwnerPermissions(); 307 parts[i].ApplyNextOwnerPermissions();
316 }
317 } 308 }
318 309
319 public string GetStateSnapshot() 310 public string GetStateSnapshot()
320 { 311 {
321 Dictionary<UUID, string> states = new Dictionary<UUID, string>(); 312 Dictionary<UUID, string> states = new Dictionary<UUID, string>();
322 313
323 foreach (SceneObjectPart part in m_parts.Values) 314 SceneObjectPart[] parts = m_parts.GetArray();
315 for (int i = 0; i < parts.Length; i++)
324 { 316 {
317 SceneObjectPart part = parts[i];
325 foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates()) 318 foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates())
326 states[s.Key] = s.Value; 319 states[s.Key] = s.Value;
327 } 320 }
328 321
329 if (states.Count < 1) 322 if (states.Count < 1)
330 return ""; 323 return String.Empty;
331 324
332 XmlDocument xmldoc = new XmlDocument(); 325 XmlDocument xmldoc = new XmlDocument();
333 326
334 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 327 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
335 "", ""); 328 String.Empty, String.Empty);
336 329
337 xmldoc.AppendChild(xmlnode); 330 xmldoc.AppendChild(xmlnode);
338 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData", 331 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData",
339 ""); 332 String.Empty);
340 333
341 xmldoc.AppendChild(rootElement); 334 xmldoc.AppendChild(rootElement);
342 335
343 336
344 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", 337 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates",
345 ""); 338 String.Empty);
346 339
347 rootElement.AppendChild(wrapper); 340 rootElement.AppendChild(wrapper);
348 341
@@ -425,10 +418,9 @@ namespace OpenSim.Region.Framework.Scenes
425 if (m_scene.RegionInfo.RegionSettings.DisableScripts) 418 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
426 return; 419 return;
427 420
428 foreach (SceneObjectPart part in m_parts.Values) 421 SceneObjectPart[] parts = m_parts.GetArray();
429 { 422 for (int i = 0; i < parts.Length; i++)
430 part.Inventory.ResumeScripts(); 423 parts[i].Inventory.ResumeScripts();
431 }
432 } 424 }
433 } 425 }
434} 426}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 142f5d8..3bc7834 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -131,89 +131,6 @@ namespace OpenSim.Region.Framework.Scenes
131 } 131 }
132 } 132 }
133 133
134 public void lockPartsForRead(bool locked)
135 {
136 if (locked)
137 {
138 if (m_partsLock.RecursiveReadCount > 0)
139 {
140 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
141 try
142 {
143 StackTrace stackTrace = new StackTrace(); // get call stack
144 StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
145
146 // write call stack method names
147 foreach (StackFrame stackFrame in stackFrames)
148 {
149 m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name
150 }
151
152 m_partsLock.ExitReadLock();
153 }
154 catch { } // Ignore errors, to allow resync
155 }
156 if (m_partsLock.RecursiveWriteCount > 0)
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
159 try
160 {
161 m_partsLock.ExitWriteLock();
162 }
163 catch { }
164
165 }
166
167 while (!m_partsLock.TryEnterReadLock(60000))
168 {
169 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
170 if (m_partsLock.IsWriteLockHeld)
171 {
172 m_partsLock = new System.Threading.ReaderWriterLockSlim();
173 }
174 }
175 }
176 else
177 {
178 if (m_partsLock.RecursiveReadCount > 0)
179 {
180 m_partsLock.ExitReadLock();
181 }
182 }
183 }
184 public void lockPartsForWrite(bool locked)
185 {
186 if (locked)
187 {
188 if (m_partsLock.RecursiveReadCount > 0)
189 {
190 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
191 m_partsLock.ExitReadLock();
192 }
193 if (m_partsLock.RecursiveWriteCount > 0)
194 {
195 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
196 m_partsLock.ExitWriteLock();
197 }
198
199 while (!m_partsLock.TryEnterWriteLock(60000))
200 {
201 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
202 if (m_partsLock.IsWriteLockHeld)
203 {
204 m_partsLock = new System.Threading.ReaderWriterLockSlim();
205 }
206 }
207 }
208 else
209 {
210 if (m_partsLock.RecursiveWriteCount > 0)
211 {
212 m_partsLock.ExitWriteLock();
213 }
214 }
215 }
216
217 public bool HasGroupChanged 134 public bool HasGroupChanged
218 { 135 {
219 set 136 set
@@ -305,17 +222,14 @@ namespace OpenSim.Region.Framework.Scenes
305 } 222 }
306 } 223 }
307 224
308 public float scriptScore = 0f; 225 public float scriptScore;
309 226
310 private Vector3 lastPhysGroupPos; 227 private Vector3 lastPhysGroupPos;
311 private Quaternion lastPhysGroupRot; 228 private Quaternion lastPhysGroupRot;
312 229
313 private bool m_isBackedUp = false; 230 private bool m_isBackedUp;
314 231
315 /// <summary> 232 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
316 /// The constituent parts of this group
317 /// </summary>
318 protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
319 233
320 protected ulong m_regionHandle; 234 protected ulong m_regionHandle;
321 protected SceneObjectPart m_rootPart; 235 protected SceneObjectPart m_rootPart;
@@ -324,13 +238,13 @@ namespace OpenSim.Region.Framework.Scenes
324 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 238 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
325 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 239 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>();
326 240
327 private bool m_scriptListens_atTarget = false; 241 private bool m_scriptListens_atTarget;
328 private bool m_scriptListens_notAtTarget = false; 242 private bool m_scriptListens_notAtTarget;
243 private bool m_scriptListens_atRotTarget;
244 private bool m_scriptListens_notAtRotTarget;
329 245
330 private bool m_scriptListens_atRotTarget = false;
331 private bool m_scriptListens_notAtRotTarget = false;
332 public bool m_dupeInProgress = false; 246 public bool m_dupeInProgress = false;
333 internal Dictionary<UUID, string> m_savedScriptState = null; 247 internal Dictionary<UUID, string> m_savedScriptState;
334 248
335 #region Properties 249 #region Properties
336 250
@@ -341,7 +255,7 @@ namespace OpenSim.Region.Framework.Scenes
341 { 255 {
342 get { 256 get {
343 if (RootPart == null) 257 if (RootPart == null)
344 return ""; 258 return String.Empty;
345 return RootPart.Name; 259 return RootPart.Name;
346 } 260 }
347 set { RootPart.Name = value; } 261 set { RootPart.Name = value; }
@@ -361,7 +275,7 @@ namespace OpenSim.Region.Framework.Scenes
361 /// </summary> 275 /// </summary>
362 public int PrimCount 276 public int PrimCount
363 { 277 {
364 get { lock (m_parts) { return m_parts.Count; } } 278 get { return m_parts.Count; }
365 } 279 }
366 280
367 protected Quaternion m_rotation = Quaternion.Identity; 281 protected Quaternion m_rotation = Quaternion.Identity;
@@ -370,17 +284,9 @@ namespace OpenSim.Region.Framework.Scenes
370 { 284 {
371 get { return m_rotation; } 285 get { return m_rotation; }
372 set { 286 set {
373 lockPartsForRead(true); 287 foreach(SceneObjectPart p in m_parts.GetArray())
374 try
375 { 288 {
376 foreach(SceneObjectPart p in m_parts.Values) 289 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
377 {
378 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
379 }
380 }
381 finally
382 {
383 lockPartsForRead(false);
384 } 290 }
385 m_rotation = value; 291 m_rotation = value;
386 } 292 }
@@ -397,16 +303,14 @@ namespace OpenSim.Region.Framework.Scenes
397 set { m_rootPart.GroupID = value; } 303 set { m_rootPart.GroupID = value; }
398 } 304 }
399 305
400 /// <value> 306 public SceneObjectPart[] Parts
401 /// The parts of this scene object group. You must lock this property before using it. 307 {
402 /// If you're doing anything other than reading values, please take a copy of the values rather than locking 308 get { return m_parts.GetArray(); }
403 /// the dictionary for the entirety of the operation. This increases liveness and reduces the danger of deadlock 309 }
404 /// If you want to know the number of children, consider using the PrimCount property instead 310
405 /// </value> 311 public bool ContainsPart(UUID partID)
406 public Dictionary<UUID, SceneObjectPart> Children
407 { 312 {
408 get { return m_parts; } 313 return m_parts.ContainsKey(partID);
409 set { m_parts = value; }
410 } 314 }
411 315
412 /// <value> 316 /// <value>
@@ -423,16 +327,9 @@ namespace OpenSim.Region.Framework.Scenes
423 set 327 set
424 { 328 {
425 m_regionHandle = value; 329 m_regionHandle = value;
426 lockPartsForRead(true); 330 SceneObjectPart[] parts = m_parts.GetArray();
427 { 331 for (int i = 0; i < parts.Length; i++)
428 foreach (SceneObjectPart part in m_parts.Values) 332 parts[i].RegionHandle = value;
429 {
430
431 part.RegionHandle = m_regionHandle;
432
433 }
434 }
435 lockPartsForRead(false);
436 } 333 }
437 } 334 }
438 335
@@ -467,8 +364,7 @@ namespace OpenSim.Region.Framework.Scenes
467 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 364 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
468 } 365 }
469 366
470 lockPartsForRead(true); 367 foreach (SceneObjectPart part in m_parts.GetArray())
471 foreach (SceneObjectPart part in m_parts.Values)
472 { 368 {
473 part.IgnoreUndoUpdate = true; 369 part.IgnoreUndoUpdate = true;
474 } 370 }
@@ -479,12 +375,10 @@ namespace OpenSim.Region.Framework.Scenes
479 RootPart.ScriptSetPhysicsStatus(false); 375 RootPart.ScriptSetPhysicsStatus(false);
480 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 376 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
481 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 377 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
482 lockPartsForRead(false);
483 return; 378 return;
484 } 379 }
485 } 380 }
486 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); 381 SceneObjectPart[] parts = m_parts.GetArray();
487 lockPartsForRead(false);
488 foreach (SceneObjectPart part in parts) 382 foreach (SceneObjectPart part in parts)
489 { 383 {
490 part.IgnoreUndoUpdate = false; 384 part.IgnoreUndoUpdate = false;
@@ -499,10 +393,14 @@ namespace OpenSim.Region.Framework.Scenes
499 { 393 {
500 foreach (ScenePresence av in m_linkedAvatars) 394 foreach (ScenePresence av in m_linkedAvatars)
501 { 395 {
502 Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; 396 SceneObjectPart p;
503 av.AbsolutePosition += offset; 397 if (m_parts.TryGetValue(av.LinkedPrim, out p))
504 av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition 398 {
505 av.SendFullUpdateToAllClients(); 399 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
400 av.AbsolutePosition += offset;
401 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
402 av.SendFullUpdateToAllClients();
403 }
506 } 404 }
507 } 405 }
508 406
@@ -526,14 +424,9 @@ namespace OpenSim.Region.Framework.Scenes
526 { 424 {
527 get { return m_rootPart.UUID; } 425 get { return m_rootPart.UUID; }
528 set 426 set
529 { 427 {
530 m_rootPart.UUID = value; 428 m_rootPart.UUID = value;
531 429 m_parts.AddOrReplace(value, m_rootPart);
532 lock (m_parts)
533 {
534 m_parts.Remove(m_rootPart.UUID);
535 m_parts.Add(m_rootPart.UUID, m_rootPart);
536 }
537 } 430 }
538 } 431 }
539 432
@@ -595,12 +488,12 @@ namespace OpenSim.Region.Framework.Scenes
595 { 488 {
596 m_rootPart.PhysActor.Selected = value; 489 m_rootPart.PhysActor.Selected = value;
597 // Pass it on to the children. 490 // Pass it on to the children.
598 foreach (SceneObjectPart child in Children.Values) 491 SceneObjectPart[] parts = m_parts.GetArray();
492 for (int i = 0; i < parts.Length; i++)
599 { 493 {
494 SceneObjectPart child = parts[i];
600 if (child.PhysActor != null) 495 if (child.PhysActor != null)
601 {
602 child.PhysActor.Selected = value; 496 child.PhysActor.Selected = value;
603 }
604 } 497 }
605 } 498 }
606 } 499 }
@@ -704,16 +597,9 @@ namespace OpenSim.Region.Framework.Scenes
704 597
705 public void SetFromItemID(UUID AssetId) 598 public void SetFromItemID(UUID AssetId)
706 { 599 {
707 lockPartsForRead(true); 600 SceneObjectPart[] parts = m_parts.GetArray();
708 { 601 for (int i = 0; i < parts.Length; i++)
709 foreach (SceneObjectPart part in m_parts.Values) 602 parts[i].FromItemID = AssetId;
710 {
711
712 part.FromItemID = AssetId;
713
714 }
715 }
716 lockPartsForRead(false);
717 } 603 }
718 604
719 public UUID GetFromItemID() 605 public UUID GetFromItemID()
@@ -755,23 +641,18 @@ namespace OpenSim.Region.Framework.Scenes
755 if (m_rootPart.LocalId == 0) 641 if (m_rootPart.LocalId == 0)
756 m_rootPart.LocalId = m_scene.AllocateLocalId(); 642 m_rootPart.LocalId = m_scene.AllocateLocalId();
757 643
758 lock (m_parts) 644 SceneObjectPart[] parts = m_parts.GetArray();
645 for (int i = 0; i < parts.Length; i++)
759 { 646 {
760 foreach (SceneObjectPart part in m_parts.Values) 647 SceneObjectPart part = parts[i];
761 { 648 if (Object.ReferenceEquals(part, m_rootPart))
762 if (Object.ReferenceEquals(part, m_rootPart)) 649 continue;
763 { 650
764 continue; 651 if (part.LocalId == 0)
765 } 652 part.LocalId = m_scene.AllocateLocalId();
766 653
767 if (part.LocalId == 0) 654 part.ParentID = m_rootPart.LocalId;
768 { 655 //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);
769 part.LocalId = m_scene.AllocateLocalId();
770 }
771
772 part.ParentID = m_rootPart.LocalId;
773 //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);
774 }
775 } 656 }
776 657
777 ApplyPhysics(m_scene.m_physicalPrim); 658 ApplyPhysics(m_scene.m_physicalPrim);
@@ -787,24 +668,21 @@ namespace OpenSim.Region.Framework.Scenes
787 Vector3 maxScale = Vector3.Zero; 668 Vector3 maxScale = Vector3.Zero;
788 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 669 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
789 670
790 lockPartsForRead(true); 671 SceneObjectPart[] parts = m_parts.GetArray();
672 for (int i = 0; i < parts.Length; i++)
791 { 673 {
792 foreach (SceneObjectPart part in m_parts.Values) 674 SceneObjectPart part = parts[i];
793 { 675 Vector3 partscale = part.Scale;
794 Vector3 partscale = part.Scale; 676 Vector3 partoffset = part.OffsetPosition;
795 Vector3 partoffset = part.OffsetPosition;
796 677
797 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; 678 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
798 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; 679 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
799 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; 680 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
800 681
801 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 682 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
802 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 683 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
803 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 684 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
804
805 }
806 } 685 }
807 lockPartsForRead(false);
808 686
809 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 687 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
810 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 688 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
@@ -821,42 +699,40 @@ namespace OpenSim.Region.Framework.Scenes
821 699
822 EntityIntersection result = new EntityIntersection(); 700 EntityIntersection result = new EntityIntersection();
823 701
824 lockPartsForRead(true); 702 SceneObjectPart[] parts = m_parts.GetArray();
703 for (int i = 0; i < parts.Length; i++)
825 { 704 {
826 foreach (SceneObjectPart part in m_parts.Values) 705 SceneObjectPart part = parts[i];
827 { 706
828 707 // Temporary commented to stop compiler warning
829 // Temporary commented to stop compiler warning 708 //Vector3 partPosition =
830 //Vector3 partPosition = 709 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
831 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 710 Quaternion parentrotation = GroupRotation;
832 Quaternion parentrotation = GroupRotation;
833 711
834 // Telling the prim to raytrace. 712 // Telling the prim to raytrace.
835 //EntityIntersection inter = part.TestIntersection(hRay, parentrotation); 713 //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
836 714
837 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation,frontFacesOnly, faceCenters); 715 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
838 716
839 // This may need to be updated to the maximum draw distance possible.. 717 // This may need to be updated to the maximum draw distance possible..
840 // We might (and probably will) be checking for prim creation from other sims 718 // We might (and probably will) be checking for prim creation from other sims
841 // when the camera crosses the border. 719 // when the camera crosses the border.
842 float idist = Constants.RegionSize; 720 float idist = Constants.RegionSize;
843 721
844 if (inter.HitTF) 722 if (inter.HitTF)
723 {
724 // We need to find the closest prim to return to the testcaller along the ray
725 if (inter.distance < idist)
845 { 726 {
846 // We need to find the closest prim to return to the testcaller along the ray 727 result.HitTF = true;
847 if (inter.distance < idist) 728 result.ipoint = inter.ipoint;
848 { 729 result.obj = part;
849 result.HitTF = true; 730 result.normal = inter.normal;
850 result.ipoint = inter.ipoint; 731 result.distance = inter.distance;
851 result.obj = part;
852 result.normal = inter.normal;
853 result.distance = inter.distance;
854 }
855 } 732 }
856 733
857 } 734 }
858 } 735 }
859 lockPartsForRead(false);
860 return result; 736 return result;
861 } 737 }
862 738
@@ -875,243 +751,239 @@ namespace OpenSim.Region.Framework.Scenes
875 minY = 256f; 751 minY = 256f;
876 minZ = 8192f; 752 minZ = 8192f;
877 753
878 lockPartsForRead(true); 754 SceneObjectPart[] parts = m_parts.GetArray();
755 foreach (SceneObjectPart part in parts)
879 { 756 {
880 foreach (SceneObjectPart part in m_parts.Values) 757 Vector3 worldPos = part.GetWorldPosition();
758 Vector3 offset = worldPos - AbsolutePosition;
759 Quaternion worldRot;
760 if (part.ParentID == 0)
881 { 761 {
882 762 worldRot = part.RotationOffset;
883 Vector3 worldPos = part.GetWorldPosition(); 763 }
884 Vector3 offset = worldPos - AbsolutePosition; 764 else
885 Quaternion worldRot; 765 {
886 if (part.ParentID == 0) 766 worldRot = part.GetWorldRotation();
887 { 767 }
888 worldRot = part.RotationOffset;
889 }
890 else
891 {
892 worldRot = part.GetWorldRotation();
893 }
894 768
895 Vector3 frontTopLeft; 769 Vector3 frontTopLeft;
896 Vector3 frontTopRight; 770 Vector3 frontTopRight;
897 Vector3 frontBottomLeft; 771 Vector3 frontBottomLeft;
898 Vector3 frontBottomRight; 772 Vector3 frontBottomRight;
899 773
900 Vector3 backTopLeft; 774 Vector3 backTopLeft;
901 Vector3 backTopRight; 775 Vector3 backTopRight;
902 Vector3 backBottomLeft; 776 Vector3 backBottomLeft;
903 Vector3 backBottomRight; 777 Vector3 backBottomRight;
904 778
905 // Vector3[] corners = new Vector3[8]; 779 // Vector3[] corners = new Vector3[8];
906 780
907 Vector3 orig = Vector3.Zero; 781 Vector3 orig = Vector3.Zero;
908 782
909 frontTopLeft.X = orig.X - (part.Scale.X / 2); 783 frontTopLeft.X = orig.X - (part.Scale.X / 2);
910 frontTopLeft.Y = orig.Y - (part.Scale.Y / 2); 784 frontTopLeft.Y = orig.Y - (part.Scale.Y / 2);
911 frontTopLeft.Z = orig.Z + (part.Scale.Z / 2); 785 frontTopLeft.Z = orig.Z + (part.Scale.Z / 2);
912 786
913 frontTopRight.X = orig.X - (part.Scale.X / 2); 787 frontTopRight.X = orig.X - (part.Scale.X / 2);
914 frontTopRight.Y = orig.Y + (part.Scale.Y / 2); 788 frontTopRight.Y = orig.Y + (part.Scale.Y / 2);
915 frontTopRight.Z = orig.Z + (part.Scale.Z / 2); 789 frontTopRight.Z = orig.Z + (part.Scale.Z / 2);
916 790
917 frontBottomLeft.X = orig.X - (part.Scale.X / 2); 791 frontBottomLeft.X = orig.X - (part.Scale.X / 2);
918 frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2); 792 frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
919 frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2); 793 frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
920 794
921 frontBottomRight.X = orig.X - (part.Scale.X / 2); 795 frontBottomRight.X = orig.X - (part.Scale.X / 2);
922 frontBottomRight.Y = orig.Y + (part.Scale.Y / 2); 796 frontBottomRight.Y = orig.Y + (part.Scale.Y / 2);
923 frontBottomRight.Z = orig.Z - (part.Scale.Z / 2); 797 frontBottomRight.Z = orig.Z - (part.Scale.Z / 2);
924 798
925 backTopLeft.X = orig.X + (part.Scale.X / 2); 799 backTopLeft.X = orig.X + (part.Scale.X / 2);
926 backTopLeft.Y = orig.Y - (part.Scale.Y / 2); 800 backTopLeft.Y = orig.Y - (part.Scale.Y / 2);
927 backTopLeft.Z = orig.Z + (part.Scale.Z / 2); 801 backTopLeft.Z = orig.Z + (part.Scale.Z / 2);
928 802
929 backTopRight.X = orig.X + (part.Scale.X / 2); 803 backTopRight.X = orig.X + (part.Scale.X / 2);
930 backTopRight.Y = orig.Y + (part.Scale.Y / 2); 804 backTopRight.Y = orig.Y + (part.Scale.Y / 2);
931 backTopRight.Z = orig.Z + (part.Scale.Z / 2); 805 backTopRight.Z = orig.Z + (part.Scale.Z / 2);
932 806
933 backBottomLeft.X = orig.X + (part.Scale.X / 2); 807 backBottomLeft.X = orig.X + (part.Scale.X / 2);
934 backBottomLeft.Y = orig.Y - (part.Scale.Y / 2); 808 backBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
935 backBottomLeft.Z = orig.Z - (part.Scale.Z / 2); 809 backBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
936 810
937 backBottomRight.X = orig.X + (part.Scale.X / 2); 811 backBottomRight.X = orig.X + (part.Scale.X / 2);
938 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 812 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
939 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 813 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
940 814
941 815
942 816
943 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 817 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
944 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 818 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
945 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 819 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
946 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); 820 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
947 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); 821 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
948 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); 822 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
949 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); 823 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
950 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); 824 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
951
952 //for (int i = 0; i < 8; i++)
953 //{
954 // corners[i] = corners[i] * worldRot;
955 // corners[i] += offset;
956
957 // if (corners[i].X > maxX)
958 // maxX = corners[i].X;
959 // if (corners[i].X < minX)
960 // minX = corners[i].X;
961
962 // if (corners[i].Y > maxY)
963 // maxY = corners[i].Y;
964 // if (corners[i].Y < minY)
965 // minY = corners[i].Y;
966
967 // if (corners[i].Z > maxZ)
968 // maxZ = corners[i].Y;
969 // if (corners[i].Z < minZ)
970 // minZ = corners[i].Z;
971 //}
972
973 frontTopLeft = frontTopLeft * worldRot;
974 frontTopRight = frontTopRight * worldRot;
975 frontBottomLeft = frontBottomLeft * worldRot;
976 frontBottomRight = frontBottomRight * worldRot;
977
978 backBottomLeft = backBottomLeft * worldRot;
979 backBottomRight = backBottomRight * worldRot;
980 backTopLeft = backTopLeft * worldRot;
981 backTopRight = backTopRight * worldRot;
982
983
984 frontTopLeft += offset;
985 frontTopRight += offset;
986 frontBottomLeft += offset;
987 frontBottomRight += offset;
988
989 backBottomLeft += offset;
990 backBottomRight += offset;
991 backTopLeft += offset;
992 backTopRight += offset;
993
994 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
995 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
996 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
997 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
998 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
999 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1000 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1001 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1002
1003 if (frontTopRight.X > maxX)
1004 maxX = frontTopRight.X;
1005 if (frontTopLeft.X > maxX)
1006 maxX = frontTopLeft.X;
1007 if (frontBottomRight.X > maxX)
1008 maxX = frontBottomRight.X;
1009 if (frontBottomLeft.X > maxX)
1010 maxX = frontBottomLeft.X;
1011
1012 if (backTopRight.X > maxX)
1013 maxX = backTopRight.X;
1014 if (backTopLeft.X > maxX)
1015 maxX = backTopLeft.X;
1016 if (backBottomRight.X > maxX)
1017 maxX = backBottomRight.X;
1018 if (backBottomLeft.X > maxX)
1019 maxX = backBottomLeft.X;
1020
1021 if (frontTopRight.X < minX)
1022 minX = frontTopRight.X;
1023 if (frontTopLeft.X < minX)
1024 minX = frontTopLeft.X;
1025 if (frontBottomRight.X < minX)
1026 minX = frontBottomRight.X;
1027 if (frontBottomLeft.X < minX)
1028 minX = frontBottomLeft.X;
1029
1030 if (backTopRight.X < minX)
1031 minX = backTopRight.X;
1032 if (backTopLeft.X < minX)
1033 minX = backTopLeft.X;
1034 if (backBottomRight.X < minX)
1035 minX = backBottomRight.X;
1036 if (backBottomLeft.X < minX)
1037 minX = backBottomLeft.X;
1038 825
1039 // 826 //for (int i = 0; i < 8; i++)
1040 if (frontTopRight.Y > maxY) 827 //{
1041 maxY = frontTopRight.Y; 828 // corners[i] = corners[i] * worldRot;
1042 if (frontTopLeft.Y > maxY) 829 // corners[i] += offset;
1043 maxY = frontTopLeft.Y; 830
1044 if (frontBottomRight.Y > maxY) 831 // if (corners[i].X > maxX)
1045 maxY = frontBottomRight.Y; 832 // maxX = corners[i].X;
1046 if (frontBottomLeft.Y > maxY) 833 // if (corners[i].X < minX)
1047 maxY = frontBottomLeft.Y; 834 // minX = corners[i].X;
1048 835
1049 if (backTopRight.Y > maxY) 836 // if (corners[i].Y > maxY)
1050 maxY = backTopRight.Y; 837 // maxY = corners[i].Y;
1051 if (backTopLeft.Y > maxY) 838 // if (corners[i].Y < minY)
1052 maxY = backTopLeft.Y; 839 // minY = corners[i].Y;
1053 if (backBottomRight.Y > maxY) 840
1054 maxY = backBottomRight.Y; 841 // if (corners[i].Z > maxZ)
1055 if (backBottomLeft.Y > maxY) 842 // maxZ = corners[i].Y;
1056 maxY = backBottomLeft.Y; 843 // if (corners[i].Z < minZ)
1057 844 // minZ = corners[i].Z;
1058 if (frontTopRight.Y < minY) 845 //}
1059 minY = frontTopRight.Y;
1060 if (frontTopLeft.Y < minY)
1061 minY = frontTopLeft.Y;
1062 if (frontBottomRight.Y < minY)
1063 minY = frontBottomRight.Y;
1064 if (frontBottomLeft.Y < minY)
1065 minY = frontBottomLeft.Y;
1066
1067 if (backTopRight.Y < minY)
1068 minY = backTopRight.Y;
1069 if (backTopLeft.Y < minY)
1070 minY = backTopLeft.Y;
1071 if (backBottomRight.Y < minY)
1072 minY = backBottomRight.Y;
1073 if (backBottomLeft.Y < minY)
1074 minY = backBottomLeft.Y;
1075 846
1076 // 847 frontTopLeft = frontTopLeft * worldRot;
1077 if (frontTopRight.Z > maxZ) 848 frontTopRight = frontTopRight * worldRot;
1078 maxZ = frontTopRight.Z; 849 frontBottomLeft = frontBottomLeft * worldRot;
1079 if (frontTopLeft.Z > maxZ) 850 frontBottomRight = frontBottomRight * worldRot;
1080 maxZ = frontTopLeft.Z; 851
1081 if (frontBottomRight.Z > maxZ) 852 backBottomLeft = backBottomLeft * worldRot;
1082 maxZ = frontBottomRight.Z; 853 backBottomRight = backBottomRight * worldRot;
1083 if (frontBottomLeft.Z > maxZ) 854 backTopLeft = backTopLeft * worldRot;
1084 maxZ = frontBottomLeft.Z; 855 backTopRight = backTopRight * worldRot;
1085 856
1086 if (backTopRight.Z > maxZ) 857
1087 maxZ = backTopRight.Z; 858 frontTopLeft += offset;
1088 if (backTopLeft.Z > maxZ) 859 frontTopRight += offset;
1089 maxZ = backTopLeft.Z; 860 frontBottomLeft += offset;
1090 if (backBottomRight.Z > maxZ) 861 frontBottomRight += offset;
1091 maxZ = backBottomRight.Z; 862
1092 if (backBottomLeft.Z > maxZ) 863 backBottomLeft += offset;
1093 maxZ = backBottomLeft.Z; 864 backBottomRight += offset;
1094 865 backTopLeft += offset;
1095 if (frontTopRight.Z < minZ) 866 backTopRight += offset;
1096 minZ = frontTopRight.Z; 867
1097 if (frontTopLeft.Z < minZ) 868 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1098 minZ = frontTopLeft.Z; 869 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1099 if (frontBottomRight.Z < minZ) 870 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1100 minZ = frontBottomRight.Z; 871 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1101 if (frontBottomLeft.Z < minZ) 872 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1102 minZ = frontBottomLeft.Z; 873 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1103 874 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1104 if (backTopRight.Z < minZ) 875 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1105 minZ = backTopRight.Z; 876
1106 if (backTopLeft.Z < minZ) 877 if (frontTopRight.X > maxX)
1107 minZ = backTopLeft.Z; 878 maxX = frontTopRight.X;
1108 if (backBottomRight.Z < minZ) 879 if (frontTopLeft.X > maxX)
1109 minZ = backBottomRight.Z; 880 maxX = frontTopLeft.X;
1110 if (backBottomLeft.Z < minZ) 881 if (frontBottomRight.X > maxX)
1111 minZ = backBottomLeft.Z; 882 maxX = frontBottomRight.X;
1112 } 883 if (frontBottomLeft.X > maxX)
884 maxX = frontBottomLeft.X;
885
886 if (backTopRight.X > maxX)
887 maxX = backTopRight.X;
888 if (backTopLeft.X > maxX)
889 maxX = backTopLeft.X;
890 if (backBottomRight.X > maxX)
891 maxX = backBottomRight.X;
892 if (backBottomLeft.X > maxX)
893 maxX = backBottomLeft.X;
894
895 if (frontTopRight.X < minX)
896 minX = frontTopRight.X;
897 if (frontTopLeft.X < minX)
898 minX = frontTopLeft.X;
899 if (frontBottomRight.X < minX)
900 minX = frontBottomRight.X;
901 if (frontBottomLeft.X < minX)
902 minX = frontBottomLeft.X;
903
904 if (backTopRight.X < minX)
905 minX = backTopRight.X;
906 if (backTopLeft.X < minX)
907 minX = backTopLeft.X;
908 if (backBottomRight.X < minX)
909 minX = backBottomRight.X;
910 if (backBottomLeft.X < minX)
911 minX = backBottomLeft.X;
912
913 //
914 if (frontTopRight.Y > maxY)
915 maxY = frontTopRight.Y;
916 if (frontTopLeft.Y > maxY)
917 maxY = frontTopLeft.Y;
918 if (frontBottomRight.Y > maxY)
919 maxY = frontBottomRight.Y;
920 if (frontBottomLeft.Y > maxY)
921 maxY = frontBottomLeft.Y;
922
923 if (backTopRight.Y > maxY)
924 maxY = backTopRight.Y;
925 if (backTopLeft.Y > maxY)
926 maxY = backTopLeft.Y;
927 if (backBottomRight.Y > maxY)
928 maxY = backBottomRight.Y;
929 if (backBottomLeft.Y > maxY)
930 maxY = backBottomLeft.Y;
931
932 if (frontTopRight.Y < minY)
933 minY = frontTopRight.Y;
934 if (frontTopLeft.Y < minY)
935 minY = frontTopLeft.Y;
936 if (frontBottomRight.Y < minY)
937 minY = frontBottomRight.Y;
938 if (frontBottomLeft.Y < minY)
939 minY = frontBottomLeft.Y;
940
941 if (backTopRight.Y < minY)
942 minY = backTopRight.Y;
943 if (backTopLeft.Y < minY)
944 minY = backTopLeft.Y;
945 if (backBottomRight.Y < minY)
946 minY = backBottomRight.Y;
947 if (backBottomLeft.Y < minY)
948 minY = backBottomLeft.Y;
949
950 //
951 if (frontTopRight.Z > maxZ)
952 maxZ = frontTopRight.Z;
953 if (frontTopLeft.Z > maxZ)
954 maxZ = frontTopLeft.Z;
955 if (frontBottomRight.Z > maxZ)
956 maxZ = frontBottomRight.Z;
957 if (frontBottomLeft.Z > maxZ)
958 maxZ = frontBottomLeft.Z;
959
960 if (backTopRight.Z > maxZ)
961 maxZ = backTopRight.Z;
962 if (backTopLeft.Z > maxZ)
963 maxZ = backTopLeft.Z;
964 if (backBottomRight.Z > maxZ)
965 maxZ = backBottomRight.Z;
966 if (backBottomLeft.Z > maxZ)
967 maxZ = backBottomLeft.Z;
968
969 if (frontTopRight.Z < minZ)
970 minZ = frontTopRight.Z;
971 if (frontTopLeft.Z < minZ)
972 minZ = frontTopLeft.Z;
973 if (frontBottomRight.Z < minZ)
974 minZ = frontBottomRight.Z;
975 if (frontBottomLeft.Z < minZ)
976 minZ = frontBottomLeft.Z;
977
978 if (backTopRight.Z < minZ)
979 minZ = backTopRight.Z;
980 if (backTopLeft.Z < minZ)
981 minZ = backTopLeft.Z;
982 if (backBottomRight.Z < minZ)
983 minZ = backBottomRight.Z;
984 if (backBottomLeft.Z < minZ)
985 minZ = backBottomLeft.Z;
1113 } 986 }
1114 lockPartsForRead(false);
1115 } 987 }
1116 988
1117 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 989 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -1155,21 +1027,13 @@ namespace OpenSim.Region.Framework.Scenes
1155 XmlDocument doc = new XmlDocument(); 1027 XmlDocument doc = new XmlDocument();
1156 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1028 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1157 1029
1158 // Capture script state while holding the lock 1030 SceneObjectPart[] parts = m_parts.GetArray();
1159 lockPartsForRead(true); 1031 for (int i = 0; i < parts.Length; i++)
1160 { 1032 {
1161 foreach (SceneObjectPart part in m_parts.Values) 1033 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates();
1162 { 1034 foreach (KeyValuePair<UUID, string> kvp in pstates)
1163 1035 states.Add(kvp.Key, kvp.Value);
1164 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
1165 foreach (UUID itemid in pstates.Keys)
1166 {
1167 states.Add(itemid, pstates[itemid]);
1168 }
1169
1170 }
1171 } 1036 }
1172 lockPartsForRead(false);
1173 1037
1174 if (states.Count > 0) 1038 if (states.Count > 0)
1175 { 1039 {
@@ -1255,7 +1119,7 @@ namespace OpenSim.Region.Framework.Scenes
1255 //Anakin Lohner bug #3839 1119 //Anakin Lohner bug #3839
1256 lock (m_parts) 1120 lock (m_parts)
1257 { 1121 {
1258 foreach (SceneObjectPart p in m_parts.Values) 1122 foreach (SceneObjectPart p in m_parts.GetArray())
1259 { 1123 {
1260 p.AttachedAvatar = agentID; 1124 p.AttachedAvatar = agentID;
1261 } 1125 }
@@ -1326,15 +1190,10 @@ namespace OpenSim.Region.Framework.Scenes
1326 1190
1327 AbsolutePosition = detachedpos; 1191 AbsolutePosition = detachedpos;
1328 m_rootPart.AttachedAvatar = UUID.Zero; 1192 m_rootPart.AttachedAvatar = UUID.Zero;
1329 1193
1330 //Anakin Lohner bug #3839 1194 SceneObjectPart[] parts = m_parts.GetArray();
1331 lock (m_parts) 1195 for (int i = 0; i < parts.Length; i++)
1332 { 1196 parts[i].AttachedAvatar = UUID.Zero;
1333 foreach (SceneObjectPart p in m_parts.Values)
1334 {
1335 p.AttachedAvatar = UUID.Zero;
1336 }
1337 }
1338 1197
1339 m_rootPart.SetParentLocalId(0); 1198 m_rootPart.SetParentLocalId(0);
1340 SetAttachmentPoint((byte)0); 1199 SetAttachmentPoint((byte)0);
@@ -1359,15 +1218,10 @@ namespace OpenSim.Region.Framework.Scenes
1359 } 1218 }
1360 1219
1361 m_rootPart.AttachedAvatar = UUID.Zero; 1220 m_rootPart.AttachedAvatar = UUID.Zero;
1362 1221
1363 //Anakin Lohner bug #3839 1222 SceneObjectPart[] parts = m_parts.GetArray();
1364 lock (m_parts) 1223 for (int i = 0; i < parts.Length; i++)
1365 { 1224 parts[i].AttachedAvatar = UUID.Zero;
1366 foreach (SceneObjectPart p in m_parts.Values)
1367 {
1368 p.AttachedAvatar = UUID.Zero;
1369 }
1370 }
1371 1225
1372 m_rootPart.SetParentLocalId(0); 1226 m_rootPart.SetParentLocalId(0);
1373 //m_rootPart.SetAttachmentPoint((byte)0); 1227 //m_rootPart.SetAttachmentPoint((byte)0);
@@ -1390,16 +1244,9 @@ namespace OpenSim.Region.Framework.Scenes
1390 1244
1391 public override void UpdateMovement() 1245 public override void UpdateMovement()
1392 { 1246 {
1393 lockPartsForRead(true); 1247 SceneObjectPart[] parts = m_parts.GetArray();
1394 { 1248 for (int i = 0; i < parts.Length; i++)
1395 foreach (SceneObjectPart part in m_parts.Values) 1249 parts[i].UpdateMovement();
1396 {
1397
1398 part.UpdateMovement();
1399
1400 }
1401 }
1402 lockPartsForRead(false);
1403 } 1250 }
1404 1251
1405 public ushort GetTimeDilation() 1252 public ushort GetTimeDilation()
@@ -1432,8 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes
1432 part.ParentID = 0; 1279 part.ParentID = 0;
1433 part.LinkNum = 0; 1280 part.LinkNum = 0;
1434 1281
1435 lock (m_parts) 1282 m_parts.Add(m_rootPart.UUID, m_rootPart);
1436 m_parts.Add(m_rootPart.UUID, m_rootPart);
1437 } 1283 }
1438 1284
1439 /// <summary> 1285 /// <summary>
@@ -1442,17 +1288,13 @@ namespace OpenSim.Region.Framework.Scenes
1442 /// <param name="part"></param> 1288 /// <param name="part"></param>
1443 public void AddPart(SceneObjectPart part) 1289 public void AddPart(SceneObjectPart part)
1444 { 1290 {
1445 lockPartsForWrite(true); 1291 part.SetParent(this);
1446 { 1292 m_parts.Add(part.UUID, part);
1447 part.SetParent(this);
1448 m_parts.Add(part.UUID, part);
1449 1293
1450 part.LinkNum = m_parts.Count; 1294 part.LinkNum = m_parts.Count;
1451 1295
1452 if (part.LinkNum == 2 && RootPart != null) 1296 if (part.LinkNum == 2 && RootPart != null)
1453 RootPart.LinkNum = 1; 1297 RootPart.LinkNum = 1;
1454 }
1455 lockPartsForWrite(false);
1456 } 1298 }
1457 1299
1458 /// <summary> 1300 /// <summary>
@@ -1460,33 +1302,20 @@ namespace OpenSim.Region.Framework.Scenes
1460 /// </summary> 1302 /// </summary>
1461 private void UpdateParentIDs() 1303 private void UpdateParentIDs()
1462 { 1304 {
1463 lockPartsForRead(true); 1305 SceneObjectPart[] parts = m_parts.GetArray();
1306 for (int i = 0; i < parts.Length; i++)
1464 { 1307 {
1465 foreach (SceneObjectPart part in m_parts.Values) 1308 SceneObjectPart part = parts[i];
1466 { 1309 if (part.UUID != m_rootPart.UUID)
1467 1310 part.ParentID = m_rootPart.LocalId;
1468 if (part.UUID != m_rootPart.UUID)
1469 {
1470 part.ParentID = m_rootPart.LocalId;
1471 }
1472
1473 }
1474 } 1311 }
1475 lockPartsForRead(false);
1476 } 1312 }
1477 1313
1478 public void RegenerateFullIDs() 1314 public void RegenerateFullIDs()
1479 { 1315 {
1480 lockPartsForRead(true); 1316 SceneObjectPart[] parts = m_parts.GetArray();
1481 { 1317 for (int i = 0; i < parts.Length; i++)
1482 foreach (SceneObjectPart part in m_parts.Values) 1318 parts[i].UUID = UUID.Random();
1483 {
1484
1485 part.UUID = UUID.Random();
1486
1487 }
1488 }
1489 lockPartsForRead(false);
1490 } 1319 }
1491 1320
1492 // helper provided for parts. 1321 // helper provided for parts.
@@ -1519,7 +1348,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 1348
1520 // teravus: AbsolutePosition is NOT a normal property! 1349 // teravus: AbsolutePosition is NOT a normal property!
1521 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1350 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1522 1351 // jhurliman: Then why is it a property instead of two methods?
1523 } 1352 }
1524 1353
1525 public UUID GetPartsFullID(uint localID) 1354 public UUID GetPartsFullID(uint localID)
@@ -1572,18 +1401,15 @@ namespace OpenSim.Region.Framework.Scenes
1572 1401
1573 DetachFromBackup(); 1402 DetachFromBackup();
1574 1403
1575 lockPartsForRead(true); 1404 SceneObjectPart[] parts = m_parts.GetArray();
1576 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); 1405 for (int i = 0; i < parts.Length; i++)
1577 lockPartsForRead(false);
1578
1579 foreach (SceneObjectPart part in parts)
1580 { 1406 {
1581 Scene.ForEachScenePresence(delegate (ScenePresence avatar) 1407 SceneObjectPart part = parts[i];
1408
1409 Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1582 { 1410 {
1583 if (avatar.ParentID == LocalId) 1411 if (avatar.ParentID == LocalId)
1584 {
1585 avatar.StandUp(); 1412 avatar.StandUp();
1586 }
1587 1413
1588 if (!silent) 1414 if (!silent)
1589 { 1415 {
@@ -1619,20 +1445,16 @@ namespace OpenSim.Region.Framework.Scenes
1619 1445
1620 scriptEvents aggregateScriptEvents = 0; 1446 scriptEvents aggregateScriptEvents = 0;
1621 1447
1622 lockPartsForRead(true); 1448 SceneObjectPart[] parts = m_parts.GetArray();
1449 for (int i = 0; i < parts.Length; i++)
1623 { 1450 {
1624 foreach (SceneObjectPart part in m_parts.Values) 1451 SceneObjectPart part = parts[i];
1625 { 1452 if (part == null)
1626 1453 continue;
1627 if (part == null) 1454 if (part != RootPart)
1628 continue; 1455 part.Flags = objectflagupdate;
1629 if (part != RootPart) 1456 aggregateScriptEvents |= part.AggregateScriptEvents;
1630 part.Flags = objectflagupdate;
1631 aggregateScriptEvents |= part.AggregateScriptEvents;
1632
1633 }
1634 } 1457 }
1635 lockPartsForRead(false);
1636 1458
1637 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1459 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1638 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1460 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1674,30 +1496,23 @@ namespace OpenSim.Region.Framework.Scenes
1674 /// <param name="m_physicalPrim"></param> 1496 /// <param name="m_physicalPrim"></param>
1675 public void ApplyPhysics(bool m_physicalPrim) 1497 public void ApplyPhysics(bool m_physicalPrim)
1676 { 1498 {
1677 lockPartsForRead(true); 1499 // Apply physics to the root prim
1500 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1678 1501
1679 if (m_parts.Count > 1) 1502 // Apply physics to child prims
1503 SceneObjectPart[] parts = m_parts.GetArray();
1504 if (parts.Length > 1)
1680 { 1505 {
1681 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); 1506 for (int i = 0; i < parts.Length; i++)
1682 lockPartsForRead(false);
1683 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1684 foreach (SceneObjectPart part in values)
1685 { 1507 {
1686 1508 SceneObjectPart part = parts[i];
1687 if (part.LocalId != m_rootPart.LocalId) 1509 if (part.LocalId != m_rootPart.LocalId)
1688 {
1689 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); 1510 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1690 }
1691
1692 } 1511 }
1512
1693 // Hack to get the physics scene geometries in the right spot 1513 // Hack to get the physics scene geometries in the right spot
1694 ResetChildPrimPhysicsPositions(); 1514 ResetChildPrimPhysicsPositions();
1695 } 1515 }
1696 else
1697 {
1698 lockPartsForRead(false);
1699 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1700 }
1701 } 1516 }
1702 1517
1703 public void SetOwnerId(UUID userId) 1518 public void SetOwnerId(UUID userId)
@@ -1712,15 +1527,9 @@ namespace OpenSim.Region.Framework.Scenes
1712 1527
1713 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1528 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1714 { 1529 {
1715 lockPartsForRead(true); 1530 SceneObjectPart[] parts = m_parts.GetArray();
1716 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); 1531 for (int i = 0; i < parts.Length; i++)
1717 lockPartsForRead(false); 1532 whatToDo(parts[i]);
1718 foreach (SceneObjectPart part in values)
1719 {
1720
1721 whatToDo(part);
1722
1723 }
1724 } 1533 }
1725 1534
1726 #region Events 1535 #region Events
@@ -1790,7 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes
1790 // Possible ghost prim 1599 // Possible ghost prim
1791 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) 1600 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1792 { 1601 {
1793 foreach (SceneObjectPart part in Children.Values) 1602 foreach (SceneObjectPart part in m_parts.GetArray())
1794 { 1603 {
1795 // Re-set physics actor positions and 1604 // Re-set physics actor positions and
1796 // orientations 1605 // orientations
@@ -1842,17 +1651,13 @@ namespace OpenSim.Region.Framework.Scenes
1842 RootPart.SendFullUpdate( 1651 RootPart.SendFullUpdate(
1843 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1652 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1844 1653
1845 lockPartsForRead(true); 1654 SceneObjectPart[] parts = m_parts.GetArray();
1655 for (int i = 0; i < parts.Length; i++)
1846 { 1656 {
1847 foreach (SceneObjectPart part in m_parts.Values) 1657 SceneObjectPart part = parts[i];
1848 { 1658 if (part != RootPart)
1849 1659 part.SendFullUpdate(remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1850 if (part != RootPart)
1851 part.SendFullUpdate(
1852 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1853 }
1854 } 1660 }
1855 lockPartsForRead(false);
1856 } 1661 }
1857 1662
1858 #region Copying 1663 #region Copying
@@ -1870,7 +1675,7 @@ namespace OpenSim.Region.Framework.Scenes
1870 m_dupeInProgress = true; 1675 m_dupeInProgress = true;
1871 dupe = (SceneObjectGroup)MemberwiseClone(); 1676 dupe = (SceneObjectGroup)MemberwiseClone();
1872 dupe.m_isBackedUp = false; 1677 dupe.m_isBackedUp = false;
1873 dupe.m_parts = new Dictionary<UUID, SceneObjectPart>(); 1678 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1874 1679
1875 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1680 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1876 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1681 // attachments do not bordercross while they're being duplicated. This is hacktastic!
@@ -1916,13 +1721,7 @@ namespace OpenSim.Region.Framework.Scenes
1916 dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); 1721 dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
1917 } 1722 }
1918 1723
1919 lockPartsForRead(true); 1724 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1920
1921 List<SceneObjectPart> partList;
1922
1923 partList = new List<SceneObjectPart>(m_parts.Values);
1924
1925 lockPartsForRead(false);
1926 1725
1927 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1726 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1928 { 1727 {
@@ -2261,14 +2060,9 @@ namespace OpenSim.Region.Framework.Scenes
2261 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2060 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2262 newPart.SetParent(this); 2061 newPart.SetParent(this);
2263 2062
2264 lockPartsForWrite(true); 2063 AddPart(newPart);
2265 {
2266 m_parts.Add(newPart.UUID, newPart);
2267 }
2268 lockPartsForWrite(false);
2269 2064
2270 SetPartAsNonRoot(newPart); 2065 SetPartAsNonRoot(newPart);
2271
2272 return newPart; 2066 return newPart;
2273 } 2067 }
2274 2068
@@ -2280,9 +2074,9 @@ namespace OpenSim.Region.Framework.Scenes
2280 /// </summary> 2074 /// </summary>
2281 public void ResetIDs() 2075 public void ResetIDs()
2282 { 2076 {
2283 lock (m_parts) 2077 lock (m_parts.SyncRoot)
2284 { 2078 {
2285 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); 2079 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.GetArray());
2286 m_parts.Clear(); 2080 m_parts.Clear();
2287 foreach (SceneObjectPart part in partsList) 2081 foreach (SceneObjectPart part in partsList)
2288 { 2082 {
@@ -2298,7 +2092,6 @@ namespace OpenSim.Region.Framework.Scenes
2298 /// <param name="part"></param> 2092 /// <param name="part"></param>
2299 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 2093 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
2300 { 2094 {
2301
2302 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, 2095 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
2303 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 2096 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
2304 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 2097 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
@@ -2329,8 +2122,6 @@ namespace OpenSim.Region.Framework.Scenes
2329 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2122 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2330 // return; 2123 // return;
2331 2124
2332 lockPartsForRead(true);
2333
2334 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2125 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
2335 2126
2336 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2127 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f))
@@ -2345,16 +2136,14 @@ namespace OpenSim.Region.Framework.Scenes
2345 lastPhysGroupRot = GroupRotation; 2136 lastPhysGroupRot = GroupRotation;
2346 } 2137 }
2347 2138
2348 List<SceneObjectPart> partList = null; 2139 SceneObjectPart[] parts = m_parts.GetArray();
2349 partList = new List<SceneObjectPart>(m_parts.Values); 2140 for (int i = 0; i < parts.Length; i++)
2350
2351 foreach (SceneObjectPart part in partList)
2352 { 2141 {
2142 SceneObjectPart part = parts[i];
2353 if (!IsSelected) 2143 if (!IsSelected)
2354 part.UpdateLookAt(); 2144 part.UpdateLookAt();
2355 part.SendScheduledUpdates(); 2145 part.SendScheduledUpdates();
2356 } 2146 }
2357 lockPartsForRead(false);
2358 } 2147 }
2359 2148
2360 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2149 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -2363,29 +2152,22 @@ namespace OpenSim.Region.Framework.Scenes
2363 2152
2364 RootPart.AddFullUpdateToAvatar(presence); 2153 RootPart.AddFullUpdateToAvatar(presence);
2365 2154
2366 lockPartsForRead(true); 2155 SceneObjectPart[] parts = m_parts.GetArray();
2156 for (int i = 0; i < parts.Length; i++)
2367 { 2157 {
2368 foreach (SceneObjectPart part in m_parts.Values) 2158 SceneObjectPart part = parts[i];
2369 { 2159 if (part != RootPart)
2370 2160 part.AddFullUpdateToAvatar(presence);
2371 if (part != RootPart)
2372 part.AddFullUpdateToAvatar(presence);
2373
2374 }
2375 } 2161 }
2376 lockPartsForRead(false);
2377 } 2162 }
2378 2163
2379 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2164 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
2380 { 2165 {
2381 lockPartsForRead(true); 2166// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
2382
2383 foreach (SceneObjectPart part in m_parts.Values)
2384 {
2385 part.AddTerseUpdateToAvatar(presence);
2386 }
2387 2167
2388 lockPartsForRead(false); 2168 SceneObjectPart[] parts = m_parts.GetArray();
2169 for (int i = 0; i < parts.Length; i++)
2170 parts[i].AddTerseUpdateToAvatar(presence);
2389 } 2171 }
2390 2172
2391 /// <summary> 2173 /// <summary>
@@ -2399,17 +2181,13 @@ namespace OpenSim.Region.Framework.Scenes
2399 checkAtTargets(); 2181 checkAtTargets();
2400 RootPart.ScheduleFullUpdate(); 2182 RootPart.ScheduleFullUpdate();
2401 2183
2402 lockPartsForRead(true); 2184 SceneObjectPart[] parts = m_parts.GetArray();
2185 for (int i = 0; i < parts.Length; i++)
2403 { 2186 {
2404 foreach (SceneObjectPart part in m_parts.Values) 2187 SceneObjectPart part = parts[i];
2405 { 2188 if (part != RootPart)
2406 2189 part.ScheduleFullUpdate();
2407 if (part != RootPart)
2408 part.ScheduleFullUpdate();
2409
2410 }
2411 } 2190 }
2412 lockPartsForRead(false);
2413 } 2191 }
2414 2192
2415 /// <summary> 2193 /// <summary>
@@ -2417,13 +2195,11 @@ namespace OpenSim.Region.Framework.Scenes
2417 /// </summary> 2195 /// </summary>
2418 public void ScheduleGroupForTerseUpdate() 2196 public void ScheduleGroupForTerseUpdate()
2419 { 2197 {
2420 lockPartsForRead(true); 2198// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
2421 foreach (SceneObjectPart part in m_parts.Values)
2422 {
2423 part.ScheduleTerseUpdate();
2424 }
2425 2199
2426 lockPartsForRead(false); 2200 SceneObjectPart[] parts = m_parts.GetArray();
2201 for (int i = 0; i < parts.Length; i++)
2202 parts[i].ScheduleTerseUpdate();
2427 } 2203 }
2428 2204
2429 /// <summary> 2205 /// <summary>
@@ -2438,17 +2214,13 @@ namespace OpenSim.Region.Framework.Scenes
2438 2214
2439 RootPart.SendFullUpdateToAllClients(); 2215 RootPart.SendFullUpdateToAllClients();
2440 2216
2441 lockPartsForRead(true); 2217 SceneObjectPart[] parts = m_parts.GetArray();
2218 for (int i = 0; i < parts.Length; i++)
2442 { 2219 {
2443 foreach (SceneObjectPart part in m_parts.Values) 2220 SceneObjectPart part = parts[i];
2444 { 2221 if (part != RootPart)
2445 2222 part.SendFullUpdateToAllClients();
2446 if (part != RootPart)
2447 part.SendFullUpdateToAllClients();
2448
2449 }
2450 } 2223 }
2451 lockPartsForRead(false);
2452 } 2224 }
2453 2225
2454 /// <summary> 2226 /// <summary>
@@ -2481,14 +2253,9 @@ namespace OpenSim.Region.Framework.Scenes
2481 if (IsDeleted) 2253 if (IsDeleted)
2482 return; 2254 return;
2483 2255
2484 lockPartsForRead(true); 2256 SceneObjectPart[] parts = m_parts.GetArray();
2485 { 2257 for (int i = 0; i < parts.Length; i++)
2486 foreach (SceneObjectPart part in m_parts.Values) 2258 parts[i].SendTerseUpdateToAllClients();
2487 {
2488 part.SendTerseUpdateToAllClients();
2489 }
2490 }
2491 lockPartsForRead(false);
2492 } 2259 }
2493 2260
2494 #endregion 2261 #endregion
@@ -2502,18 +2269,12 @@ namespace OpenSim.Region.Framework.Scenes
2502 /// <returns>null if no child part with that linknum or child part</returns> 2269 /// <returns>null if no child part with that linknum or child part</returns>
2503 public SceneObjectPart GetLinkNumPart(int linknum) 2270 public SceneObjectPart GetLinkNumPart(int linknum)
2504 { 2271 {
2505 lockPartsForRead(true); 2272 SceneObjectPart[] parts = m_parts.GetArray();
2273 for (int i = 0; i < parts.Length; i++)
2506 { 2274 {
2507 foreach (SceneObjectPart part in m_parts.Values) 2275 if (parts[i].LinkNum == linknum)
2508 { 2276 return parts[i];
2509 if (part.LinkNum == linknum)
2510 {
2511 lockPartsForRead(false);
2512 return part;
2513 }
2514 }
2515 } 2277 }
2516 lockPartsForRead(false);
2517 2278
2518 return null; 2279 return null;
2519 } 2280 }
@@ -2526,8 +2287,7 @@ namespace OpenSim.Region.Framework.Scenes
2526 public SceneObjectPart GetChildPart(UUID primID) 2287 public SceneObjectPart GetChildPart(UUID primID)
2527 { 2288 {
2528 SceneObjectPart childPart; 2289 SceneObjectPart childPart;
2529 lock (m_parts) 2290 m_parts.TryGetValue(primID, out childPart);
2530 m_parts.TryGetValue(primID, out childPart);
2531 return childPart; 2291 return childPart;
2532 } 2292 }
2533 2293
@@ -2538,20 +2298,12 @@ namespace OpenSim.Region.Framework.Scenes
2538 /// <returns>null if a child part with the local ID was not found</returns> 2298 /// <returns>null if a child part with the local ID was not found</returns>
2539 public SceneObjectPart GetChildPart(uint localID) 2299 public SceneObjectPart GetChildPart(uint localID)
2540 { 2300 {
2541 //m_log.DebugFormat("Entered looking for {0}", localID); 2301 SceneObjectPart[] parts = m_parts.GetArray();
2542 lockPartsForRead(true); 2302 for (int i = 0; i < parts.Length; i++)
2543 { 2303 {
2544 foreach (SceneObjectPart part in m_parts.Values) 2304 if (parts[i].LocalId == localID)
2545 { 2305 return parts[i];
2546 //m_log.DebugFormat("Found {0}", part.LocalId);
2547 if (part.LocalId == localID)
2548 {
2549 lockPartsForRead(false);
2550 return part;
2551 }
2552 }
2553 } 2306 }
2554 lockPartsForRead(false);
2555 2307
2556 return null; 2308 return null;
2557 } 2309 }
@@ -2564,13 +2316,7 @@ namespace OpenSim.Region.Framework.Scenes
2564 /// <returns></returns> 2316 /// <returns></returns>
2565 public bool HasChildPrim(UUID primID) 2317 public bool HasChildPrim(UUID primID)
2566 { 2318 {
2567 lock (m_parts) 2319 return m_parts.ContainsKey(primID);
2568 {
2569 if (m_parts.ContainsKey(primID))
2570 return true;
2571 }
2572
2573 return false;
2574 } 2320 }
2575 2321
2576 /// <summary> 2322 /// <summary>
@@ -2581,20 +2327,12 @@ namespace OpenSim.Region.Framework.Scenes
2581 /// <returns></returns> 2327 /// <returns></returns>
2582 public bool HasChildPrim(uint localID) 2328 public bool HasChildPrim(uint localID)
2583 { 2329 {
2584 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2330 SceneObjectPart[] parts = m_parts.GetArray();
2585 lockPartsForRead(true); 2331 for (int i = 0; i < parts.Length; i++)
2586 { 2332 {
2587 foreach (SceneObjectPart part in m_parts.Values) 2333 if (parts[i].LocalId == localID)
2588 { 2334 return true;
2589 //m_log.DebugFormat("Found {0}", part.LocalId);
2590 if (part.LocalId == localID)
2591 {
2592 lockPartsForRead(false);
2593 return true;
2594 }
2595 }
2596 } 2335 }
2597 lockPartsForRead(false);
2598 2336
2599 return false; 2337 return false;
2600 } 2338 }
@@ -2644,58 +2382,56 @@ namespace OpenSim.Region.Framework.Scenes
2644 if (m_rootPart.LinkNum == 0) 2382 if (m_rootPart.LinkNum == 0)
2645 m_rootPart.LinkNum = 1; 2383 m_rootPart.LinkNum = 1;
2646 2384
2647 lockPartsForWrite(true); 2385 lock (m_parts.SyncRoot)
2648
2649 m_parts.Add(linkPart.UUID, linkPart);
2650
2651 lockPartsForWrite(false);
2652
2653 // Insert in terms of link numbers, the new links
2654 // before the current ones (with the exception of
2655 // the root prim. Shuffle the old ones up
2656 lockPartsForRead(true);
2657 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2658 { 2386 {
2659 if (kvp.Value.LinkNum != 1) 2387 m_parts.Add(linkPart.UUID, linkPart);
2388
2389 // Insert in terms of link numbers, the new links
2390 // before the current ones (with the exception of
2391 // the root prim. Shuffle the old ones up
2392 SceneObjectPart[] parts = m_parts.GetArray();
2393 for (int i = 0; i < parts.Length; i++)
2660 { 2394 {
2661 // Don't update root prim link number 2395 SceneObjectPart part = parts[i];
2662 kvp.Value.LinkNum += objectGroup.PrimCount; 2396 if (part.LinkNum != 1)
2397 {
2398 // Don't update root prim link number
2399 part.LinkNum += objectGroup.PrimCount;
2400 }
2663 } 2401 }
2664 } 2402 }
2665 lockPartsForRead(false);
2666 2403
2667 linkPart.LinkNum = 2; 2404 linkPart.LinkNum = 2;
2668 2405
2669 linkPart.SetParent(this); 2406 linkPart.SetParent(this);
2670 linkPart.CreateSelected = true; 2407 linkPart.CreateSelected = true;
2671 2408
2672 //if (linkPart.PhysActor != null) 2409 lock (m_parts.SyncRoot)
2673 //{
2674 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2675
2676 //linkPart.PhysActor = null;
2677 //}
2678
2679 //TODO: rest of parts
2680 int linkNum = 3;
2681 foreach (SceneObjectPart part in objectGroup.Children.Values)
2682 { 2410 {
2683 if (part.UUID != objectGroup.m_rootPart.UUID) 2411 //if (linkPart.PhysActor != null)
2412 //{
2413 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2414
2415 //linkPart.PhysActor = null;
2416 //}
2417
2418 //TODO: rest of parts
2419 int linkNum = 3;
2420 SceneObjectPart[] ogParts = objectGroup.Parts;
2421 for (int i = 0; i < ogParts.Length; i++)
2684 { 2422 {
2685 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2423 SceneObjectPart part = ogParts[i];
2424 if (part.UUID != objectGroup.m_rootPart.UUID)
2425 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2426 part.ClearUndoState();
2686 } 2427 }
2687 part.ClearUndoState();
2688 } 2428 }
2689 2429
2690 m_scene.UnlinkSceneObject(objectGroup, true); 2430 m_scene.UnlinkSceneObject(objectGroup, true);
2691 objectGroup.m_isDeleted = true; 2431 objectGroup.m_isDeleted = true;
2692 2432
2693 objectGroup.lockPartsForWrite(true);
2694
2695 objectGroup.m_parts.Clear(); 2433 objectGroup.m_parts.Clear();
2696 2434
2697 objectGroup.lockPartsForWrite(false);
2698
2699 // Can't do this yet since backup still makes use of the root part without any synchronization 2435 // Can't do this yet since backup still makes use of the root part without any synchronization
2700// objectGroup.m_rootPart = null; 2436// objectGroup.m_rootPart = null;
2701 2437
@@ -2764,23 +2500,27 @@ namespace OpenSim.Region.Framework.Scenes
2764 Quaternion worldRot = linkPart.GetWorldRotation(); 2500 Quaternion worldRot = linkPart.GetWorldRotation();
2765 2501
2766 // Remove the part from this object 2502 // Remove the part from this object
2767 lockPartsForWrite(true); 2503 lock (m_parts.SyncRoot)
2768 { 2504 {
2769 m_parts.Remove(linkPart.UUID); 2505 m_parts.Remove(linkPart.UUID);
2770 } 2506
2771 lockPartsForWrite(false); 2507 SceneObjectPart[] parts = m_parts.GetArray();
2772 lockPartsForRead(true); 2508
2773 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2509 if (parts.Length == 1 && RootPart != null)
2774 RootPart.LinkNum = 0;
2775 else
2776 {
2777 foreach (SceneObjectPart p in m_parts.Values)
2778 { 2510 {
2779 if (p.LinkNum > linkPart.LinkNum) 2511 // Single prim left
2780 p.LinkNum--; 2512 RootPart.LinkNum = 0;
2513 }
2514 else
2515 {
2516 for (int i = 0; i < parts.Length; i++)
2517 {
2518 SceneObjectPart part = parts[i];
2519 if (part.LinkNum > linkPart.LinkNum)
2520 part.LinkNum--;
2521 }
2781 } 2522 }
2782 } 2523 }
2783 lockPartsForRead(false);
2784 2524
2785 linkPart.ParentID = 0; 2525 linkPart.ParentID = 0;
2786 linkPart.LinkNum = 0; 2526 linkPart.LinkNum = 0;
@@ -2851,7 +2591,6 @@ namespace OpenSim.Region.Framework.Scenes
2851 part.SetParent(this); 2591 part.SetParent(this);
2852 part.ParentID = m_rootPart.LocalId; 2592 part.ParentID = m_rootPart.LocalId;
2853 2593
2854 // Caller locks m_parts for us
2855 m_parts.Add(part.UUID, part); 2594 m_parts.Add(part.UUID, part);
2856 2595
2857 part.LinkNum = linkNum; 2596 part.LinkNum = linkNum;
@@ -3104,28 +2843,21 @@ namespace OpenSim.Region.Framework.Scenes
3104 2843
3105 if (selectionPart != null) 2844 if (selectionPart != null)
3106 { 2845 {
3107 lockPartsForRead(true); 2846 SceneObjectPart[] parts = m_parts.GetArray();
3108 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); 2847 for (int i = 0; i < parts.Length; i++)
3109 lockPartsForRead(false);
3110 foreach (SceneObjectPart part in parts)
3111 { 2848 {
3112 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) 2849 SceneObjectPart part = parts[i];
2850 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2851 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
2852 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
3113 { 2853 {
3114 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2854 UsePhysics = false; // Reset physics
3115 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2855 break;
3116 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
3117 {
3118 UsePhysics = false; // Reset physics
3119 break;
3120 }
3121 } 2856 }
3122 } 2857 }
3123 2858
3124 foreach (SceneObjectPart part in parts) 2859 for (int i = 0; i < parts.Length; i++)
3125 { 2860 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
3126 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
3127 }
3128
3129 } 2861 }
3130 } 2862 }
3131 2863
@@ -3146,19 +2878,7 @@ namespace OpenSim.Region.Framework.Scenes
3146 /// <returns></returns> 2878 /// <returns></returns>
3147 public int GetPartCount() 2879 public int GetPartCount()
3148 { 2880 {
3149 return Children.Count; 2881 return Parts.Count();
3150 }
3151
3152 /// <summary>
3153 /// Get the parts of this scene object
3154 /// </summary>
3155 /// <returns></returns>
3156 public SceneObjectPart[] GetParts()
3157 {
3158 int numParts = Children.Count;
3159 SceneObjectPart[] partArray = new SceneObjectPart[numParts];
3160 Children.Values.CopyTo(partArray, 0);
3161 return partArray;
3162 } 2882 }
3163 2883
3164 /// <summary> 2884 /// <summary>
@@ -3178,12 +2898,9 @@ namespace OpenSim.Region.Framework.Scenes
3178 public void UpdatePermissions(UUID AgentID, byte field, uint localID, 2898 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
3179 uint mask, byte addRemTF) 2899 uint mask, byte addRemTF)
3180 { 2900 {
3181 List<SceneObjectPart> partList = null; 2901 SceneObjectPart[] parts = m_parts.GetArray();
3182 lock (m_parts) 2902 for (int i = 0; i < parts.Length; i++)
3183 partList = new List<SceneObjectPart>(m_parts.Values); 2903 parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF);
3184
3185 foreach (SceneObjectPart part in partList)
3186 part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
3187 2904
3188 HasGroupChanged = true; 2905 HasGroupChanged = true;
3189 } 2906 }
@@ -3283,15 +3000,17 @@ namespace OpenSim.Region.Framework.Scenes
3283 float y = (scale.Y / part.Scale.Y); 3000 float y = (scale.Y / part.Scale.Y);
3284 float z = (scale.Z / part.Scale.Z); 3001 float z = (scale.Z / part.Scale.Z);
3285 3002
3286 lockPartsForRead(true); 3003 SceneObjectPart[] parts;
3287 if (x > 1.0f || y > 1.0f || z > 1.0f) 3004 if (x > 1.0f || y > 1.0f || z > 1.0f)
3288 { 3005 {
3289 foreach (SceneObjectPart obPart in m_parts.Values) 3006 parts = m_parts.GetArray();
3007 for (int i = 0; i < parts.Length; i++)
3290 { 3008 {
3009 SceneObjectPart obPart = parts[i];
3291 if (obPart.UUID != m_rootPart.UUID) 3010 if (obPart.UUID != m_rootPart.UUID)
3292 { 3011 {
3293 Vector3 oldSize = new Vector3(obPart.Scale);
3294 obPart.IgnoreUndoUpdate = true; 3012 obPart.IgnoreUndoUpdate = true;
3013 Vector3 oldSize = new Vector3(obPart.Scale);
3295 3014
3296 float f = 1.0f; 3015 float f = 1.0f;
3297 float a = 1.0f; 3016 float a = 1.0f;
@@ -3349,12 +3068,11 @@ namespace OpenSim.Region.Framework.Scenes
3349 y *= a; 3068 y *= a;
3350 z *= a; 3069 z *= a;
3351 } 3070 }
3352
3353 } 3071 }
3072 obPart.IgnoreUndoUpdate = false;
3354 } 3073 }
3355 } 3074 }
3356 } 3075 }
3357 lockPartsForRead(false);
3358 3076
3359 Vector3 prevScale = part.Scale; 3077 Vector3 prevScale = part.Scale;
3360 prevScale.X *= x; 3078 prevScale.X *= x;
@@ -3367,9 +3085,12 @@ namespace OpenSim.Region.Framework.Scenes
3367 part.Resize(prevScale); 3085 part.Resize(prevScale);
3368 part.IgnoreUndoUpdate = false; 3086 part.IgnoreUndoUpdate = false;
3369 3087
3370 lockPartsForRead(true); 3088 parts = m_parts.GetArray();
3089 for (int i = 0; i < parts.Length; i++)
3371 { 3090 {
3372 foreach (SceneObjectPart obPart in m_parts.Values) 3091 SceneObjectPart obPart = parts[i];
3092 obPart.IgnoreUndoUpdate = true;
3093 if (obPart.UUID != m_rootPart.UUID)
3373 { 3094 {
3374 if (obPart.UUID != m_rootPart.UUID) 3095 if (obPart.UUID != m_rootPart.UUID)
3375 { 3096 {
@@ -3390,8 +3111,8 @@ namespace OpenSim.Region.Framework.Scenes
3390 } 3111 }
3391 obPart.IgnoreUndoUpdate = false; 3112 obPart.IgnoreUndoUpdate = false;
3392 } 3113 }
3114 obPart.IgnoreUndoUpdate = false;
3393 } 3115 }
3394 lockPartsForRead(false);
3395 3116
3396 if (part.PhysActor != null) 3117 if (part.PhysActor != null)
3397 { 3118 {
@@ -3450,10 +3171,11 @@ namespace OpenSim.Region.Framework.Scenes
3450 public void UpdateSinglePosition(Vector3 pos, uint localID) 3171 public void UpdateSinglePosition(Vector3 pos, uint localID)
3451 { 3172 {
3452 SceneObjectPart part = GetChildPart(localID); 3173 SceneObjectPart part = GetChildPart(localID);
3453 foreach (SceneObjectPart parts in Children.Values) 3174
3454 { 3175 SceneObjectPart[] parts = m_parts.GetArray();
3455 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION); 3176 for (int i = 0; i < parts.Length; i++)
3456 } 3177 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
3178
3457 if (part != null) 3179 if (part != null)
3458 { 3180 {
3459 if (part.UUID == m_rootPart.UUID) 3181 if (part.UUID == m_rootPart.UUID)
@@ -3475,10 +3197,10 @@ namespace OpenSim.Region.Framework.Scenes
3475 /// <param name="pos"></param> 3197 /// <param name="pos"></param>
3476 private void UpdateRootPosition(Vector3 pos) 3198 private void UpdateRootPosition(Vector3 pos)
3477 { 3199 {
3478 foreach (SceneObjectPart part in Children.Values) 3200 SceneObjectPart[] parts = m_parts.GetArray();
3479 { 3201 for (int i = 0; i < parts.Length; i++)
3480 part.StoreUndoState(UndoType.STATE_PRIM_POSITION); 3202 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
3481 } 3203
3482 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3204 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3483 Vector3 oldPos = 3205 Vector3 oldPos =
3484 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3206 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -3490,17 +3212,13 @@ namespace OpenSim.Region.Framework.Scenes
3490 axDiff *= Quaternion.Inverse(partRotation); 3212 axDiff *= Quaternion.Inverse(partRotation);
3491 diff = axDiff; 3213 diff = axDiff;
3492 3214
3493 lockPartsForRead(true); 3215 parts = m_parts.GetArray();
3216 for (int i = 0; i < parts.Length; i++)
3494 { 3217 {
3495 foreach (SceneObjectPart obPart in m_parts.Values) 3218 SceneObjectPart obPart = parts[i];
3496 { 3219 if (obPart.UUID != m_rootPart.UUID)
3497 if (obPart.UUID != m_rootPart.UUID) 3220 obPart.OffsetPosition = obPart.OffsetPosition + diff;
3498 {
3499 obPart.OffsetPosition = obPart.OffsetPosition + diff;
3500 }
3501 }
3502 } 3221 }
3503 lockPartsForRead(false);
3504 3222
3505 //We have to set undoing here because otherwise an undo state will be saved 3223 //We have to set undoing here because otherwise an undo state will be saved
3506 if (!m_rootPart.Undoing) 3224 if (!m_rootPart.Undoing)
@@ -3540,10 +3258,10 @@ namespace OpenSim.Region.Framework.Scenes
3540 /// <param name="rot"></param> 3258 /// <param name="rot"></param>
3541 public void UpdateGroupRotationR(Quaternion rot) 3259 public void UpdateGroupRotationR(Quaternion rot)
3542 { 3260 {
3543 foreach (SceneObjectPart parts in Children.Values) 3261 SceneObjectPart[] parts = m_parts.GetArray();
3544 { 3262 for (int i = 0; i < parts.Length; i++)
3545 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION); 3263 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3546 } 3264
3547 m_rootPart.UpdateRotation(rot); 3265 m_rootPart.UpdateRotation(rot);
3548 3266
3549 PhysicsActor actor = m_rootPart.PhysActor; 3267 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3564,10 +3282,10 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name="rot"></param> 3282 /// <param name="rot"></param>
3565 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3283 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3566 { 3284 {
3567 foreach (SceneObjectPart parts in Children.Values) 3285 SceneObjectPart[] parts = m_parts.GetArray();
3568 { 3286 for (int i = 0; i < parts.Length; i++)
3569 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION); 3287 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3570 } 3288
3571 m_rootPart.UpdateRotation(rot); 3289 m_rootPart.UpdateRotation(rot);
3572 3290
3573 PhysicsActor actor = m_rootPart.PhysActor; 3291 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3591,10 +3309,10 @@ namespace OpenSim.Region.Framework.Scenes
3591 public void UpdateSingleRotation(Quaternion rot, uint localID) 3309 public void UpdateSingleRotation(Quaternion rot, uint localID)
3592 { 3310 {
3593 SceneObjectPart part = GetChildPart(localID); 3311 SceneObjectPart part = GetChildPart(localID);
3594 foreach (SceneObjectPart parts in Children.Values) 3312 SceneObjectPart[] parts = m_parts.GetArray();
3595 { 3313 for (int i = 0; i < parts.Length; i++)
3596 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION); 3314 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3597 } 3315
3598 if (part != null) 3316 if (part != null)
3599 { 3317 {
3600 if (part.UUID == m_rootPart.UUID) 3318 if (part.UUID == m_rootPart.UUID)
@@ -3666,10 +3384,10 @@ namespace OpenSim.Region.Framework.Scenes
3666 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3384 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3667 } 3385 }
3668 3386
3669 lockPartsForRead(true); 3387 SceneObjectPart[] parts = m_parts.GetArray();
3670 3388 for (int i = 0; i < parts.Length; i++)
3671 foreach (SceneObjectPart prim in m_parts.Values)
3672 { 3389 {
3390 SceneObjectPart prim = parts[i];
3673 if (prim.UUID != m_rootPart.UUID) 3391 if (prim.UUID != m_rootPart.UUID)
3674 { 3392 {
3675 prim.IgnoreUndoUpdate = true; 3393 prim.IgnoreUndoUpdate = true;
@@ -3689,7 +3407,6 @@ namespace OpenSim.Region.Framework.Scenes
3689 { 3407 {
3690 m_rootPart.Undoing = false; 3408 m_rootPart.Undoing = false;
3691 } 3409 }
3692 lockPartsForRead(false);
3693 3410
3694 m_rootPart.ScheduleTerseUpdate(); 3411 m_rootPart.ScheduleTerseUpdate();
3695 } 3412 }
@@ -3811,18 +3528,10 @@ namespace OpenSim.Region.Framework.Scenes
3811 3528
3812 if (atTargets.Count > 0) 3529 if (atTargets.Count > 0)
3813 { 3530 {
3814 uint[] localids = new uint[0]; 3531 SceneObjectPart[] parts = m_parts.GetArray();
3815 lockPartsForRead(true); 3532 uint[] localids = new uint[parts.Length];
3816 { 3533 for (int i = 0; i < parts.Length; i++)
3817 localids = new uint[m_parts.Count]; 3534 localids[i] = parts[i].LocalId;
3818 int cntr = 0;
3819 foreach (SceneObjectPart part in m_parts.Values)
3820 {
3821 localids[cntr] = part.LocalId;
3822 cntr++;
3823 }
3824 }
3825 lockPartsForRead(false);
3826 3535
3827 for (int ctr = 0; ctr < localids.Length; ctr++) 3536 for (int ctr = 0; ctr < localids.Length; ctr++)
3828 { 3537 {
@@ -3840,19 +3549,11 @@ namespace OpenSim.Region.Framework.Scenes
3840 if (m_scriptListens_notAtTarget && !at_target) 3549 if (m_scriptListens_notAtTarget && !at_target)
3841 { 3550 {
3842 //trigger not_at_target 3551 //trigger not_at_target
3843 uint[] localids = new uint[0]; 3552 SceneObjectPart[] parts = m_parts.GetArray();
3844 lockPartsForRead(true); 3553 uint[] localids = new uint[parts.Length];
3845 { 3554 for (int i = 0; i < parts.Length; i++)
3846 localids = new uint[m_parts.Count]; 3555 localids[i] = parts[i].LocalId;
3847 int cntr = 0; 3556
3848 foreach (SceneObjectPart part in m_parts.Values)
3849 {
3850 localids[cntr] = part.LocalId;
3851 cntr++;
3852 }
3853 }
3854 lockPartsForRead(false);
3855
3856 for (int ctr = 0; ctr < localids.Length; ctr++) 3557 for (int ctr = 0; ctr < localids.Length; ctr++)
3857 { 3558 {
3858 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3559 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3892,22 +3593,10 @@ namespace OpenSim.Region.Framework.Scenes
3892 3593
3893 if (atRotTargets.Count > 0) 3594 if (atRotTargets.Count > 0)
3894 { 3595 {
3895 uint[] localids = new uint[0]; 3596 SceneObjectPart[] parts = m_parts.GetArray();
3896 lockPartsForRead(true); 3597 uint[] localids = new uint[parts.Length];
3897 try 3598 for (int i = 0; i < parts.Length; i++)
3898 { 3599 localids[i] = parts[i].LocalId;
3899 localids = new uint[m_parts.Count];
3900 int cntr = 0;
3901 foreach (SceneObjectPart part in m_parts.Values)
3902 {
3903 localids[cntr] = part.LocalId;
3904 cntr++;
3905 }
3906 }
3907 finally
3908 {
3909 lockPartsForRead(false);
3910 }
3911 3600
3912 for (int ctr = 0; ctr < localids.Length; ctr++) 3601 for (int ctr = 0; ctr < localids.Length; ctr++)
3913 { 3602 {
@@ -3925,22 +3614,10 @@ namespace OpenSim.Region.Framework.Scenes
3925 if (m_scriptListens_notAtRotTarget && !at_Rottarget) 3614 if (m_scriptListens_notAtRotTarget && !at_Rottarget)
3926 { 3615 {
3927 //trigger not_at_target 3616 //trigger not_at_target
3928 uint[] localids = new uint[0]; 3617 SceneObjectPart[] parts = m_parts.GetArray();
3929 lockPartsForRead(true); 3618 uint[] localids = new uint[parts.Length];
3930 try 3619 for (int i = 0; i < parts.Length; i++)
3931 { 3620 localids[i] = parts[i].LocalId;
3932 localids = new uint[m_parts.Count];
3933 int cntr = 0;
3934 foreach (SceneObjectPart part in m_parts.Values)
3935 {
3936 localids[cntr] = part.LocalId;
3937 cntr++;
3938 }
3939 }
3940 finally
3941 {
3942 lockPartsForRead(false);
3943 }
3944 3621
3945 for (int ctr = 0; ctr < localids.Length; ctr++) 3622 for (int ctr = 0; ctr < localids.Length; ctr++)
3946 { 3623 {
@@ -3954,45 +3631,38 @@ namespace OpenSim.Region.Framework.Scenes
3954 public float GetMass() 3631 public float GetMass()
3955 { 3632 {
3956 float retmass = 0f; 3633 float retmass = 0f;
3957 lockPartsForRead(true); 3634 SceneObjectPart[] parts = m_parts.GetArray();
3958 { 3635 for (int i = 0; i < parts.Length; i++)
3959 foreach (SceneObjectPart part in m_parts.Values) 3636 retmass += parts[i].GetMass();
3960 { 3637
3961 retmass += part.GetMass();
3962 }
3963 }
3964 lockPartsForRead(false);
3965 return retmass; 3638 return retmass;
3966 } 3639 }
3967 3640
3968 public void CheckSculptAndLoad() 3641 public void CheckSculptAndLoad()
3969 { 3642 {
3970 lockPartsForRead(true); 3643 if (IsDeleted)
3644 return;
3645 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
3646 return;
3647
3648 SceneObjectPart[] parts = m_parts.GetArray();
3649 for (int i = 0; i < parts.Length; i++)
3971 { 3650 {
3972 if (!IsDeleted) 3651 SceneObjectPart part = parts[i];
3652 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero)
3973 { 3653 {
3974 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == 0) 3654 // check if a previously decoded sculpt map has been cached
3655 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString())))
3975 { 3656 {
3976 foreach (SceneObjectPart part in m_parts.Values) 3657 part.SculptTextureCallback(part.Shape.SculptTexture, null);
3977 { 3658 }
3978 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero) 3659 else
3979 { 3660 {
3980 // check if a previously decoded sculpt map has been cached 3661 m_scene.AssetService.Get(
3981 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString()))) 3662 part.Shape.SculptTexture.ToString(), part, AssetReceived);
3982 {
3983 part.SculptTextureCallback(part.Shape.SculptTexture, null);
3984 }
3985 else
3986 {
3987 m_scene.AssetService.Get(
3988 part.Shape.SculptTexture.ToString(), part, AssetReceived);
3989 }
3990 }
3991 }
3992 } 3663 }
3993 } 3664 }
3994 } 3665 }
3995 lockPartsForRead(false);
3996 } 3666 }
3997 3667
3998 protected void AssetReceived(string id, Object sender, AssetBase asset) 3668 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -4013,17 +3683,13 @@ namespace OpenSim.Region.Framework.Scenes
4013 /// <param name="client"></param> 3683 /// <param name="client"></param>
4014 public void SetGroup(UUID GroupID, IClientAPI client) 3684 public void SetGroup(UUID GroupID, IClientAPI client)
4015 { 3685 {
4016 lockPartsForRead(true); 3686 SceneObjectPart[] parts = m_parts.GetArray();
3687 for (int i = 0; i < parts.Length; i++)
4017 { 3688 {
4018 foreach (SceneObjectPart part in m_parts.Values) 3689 SceneObjectPart part = parts[i];
4019 { 3690 part.SetGroup(GroupID, client);
4020 part.SetGroup(GroupID, client); 3691 part.Inventory.ChangeInventoryGroup(GroupID);
4021 part.Inventory.ChangeInventoryGroup(GroupID);
4022 }
4023
4024 HasGroupChanged = true;
4025 } 3692 }
4026 lockPartsForRead(false);
4027 3693
4028 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3694 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
4029 // for the same object with very different properties. The caller must schedule the update. 3695 // for the same object with very different properties. The caller must schedule the update.
@@ -4032,10 +3698,9 @@ namespace OpenSim.Region.Framework.Scenes
4032 3698
4033 public void TriggerScriptChangedEvent(Changed val) 3699 public void TriggerScriptChangedEvent(Changed val)
4034 { 3700 {
4035 foreach (SceneObjectPart part in Children.Values) 3701 SceneObjectPart[] parts = m_parts.GetArray();
4036 { 3702 for (int i = 0; i < parts.Length; i++)
4037 part.TriggerScriptChangedEvent(val); 3703 parts[i].TriggerScriptChangedEvent(val);
4038 }
4039 } 3704 }
4040 3705
4041 public override string ToString() 3706 public override string ToString()
@@ -4045,12 +3710,9 @@ namespace OpenSim.Region.Framework.Scenes
4045 3710
4046 public void SetAttachmentPoint(byte point) 3711 public void SetAttachmentPoint(byte point)
4047 { 3712 {
4048 lockPartsForRead(true); 3713 SceneObjectPart[] parts = m_parts.GetArray();
4049 { 3714 for (int i = 0; i < parts.Length; i++)
4050 foreach (SceneObjectPart part in m_parts.Values) 3715 parts[i].SetAttachmentPoint(point);
4051 part.SetAttachmentPoint(point);
4052 }
4053 lockPartsForRead(false);
4054 } 3716 }
4055 3717
4056 #region ISceneObject 3718 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index b205503..8aa17a1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -780,10 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
780 rootPart.Name = item.Name; 780 rootPart.Name = item.Name;
781 rootPart.Description = item.Description; 781 rootPart.Description = item.Description;
782 782
783 List<SceneObjectPart> partList = null; 783 SceneObjectPart[] partList = group.Parts;
784
785 lock (group.Children)
786 partList = new List<SceneObjectPart>(group.Children.Values);
787 784
788 group.SetGroup(m_part.GroupID, null); 785 group.SetGroup(m_part.GroupID, null);
789 786
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 8da9bdc..b3df1ea 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1884,7 +1884,7 @@ namespace OpenSim.Region.Framework.Scenes
1884 // 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. 1884 // 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.
1885 1885
1886 // Get our own copy of the part array, and sort into the order we want to test 1886 // Get our own copy of the part array, and sort into the order we want to test
1887 SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); 1887 SceneObjectPart[] partArray = targetPart.ParentGroup.Parts;
1888 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) 1888 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
1889 { 1889 {
1890 // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) 1890 // 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 77e477f..dc8957c 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
158 writer.WriteEndElement(); 158 writer.WriteEndElement();
159 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); 159 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
160 160
161 lock (sceneObject.Children) 161 SceneObjectPart[] parts = sceneObject.Parts;
162 for (int i = 0; i < parts.Length; i++)
162 { 163 {
163 foreach (SceneObjectPart part in sceneObject.Children.Values) 164 SceneObjectPart part = parts[i];
165 if (part.UUID != sceneObject.RootPart.UUID)
164 { 166 {
165 if (part.UUID != sceneObject.RootPart.UUID) 167 writer.WriteStartElement(String.Empty, "Part", String.Empty);
166 { 168 ToOriginalXmlFormat(part, writer);
167 writer.WriteStartElement(String.Empty, "Part", String.Empty); 169 writer.WriteEndElement();
168 ToOriginalXmlFormat(part, writer);
169 writer.WriteEndElement();
170 }
171 } 170 }
172 } 171 }
173 172
@@ -281,15 +280,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
281 sceneObject.RootPart.ToXml(writer); 280 sceneObject.RootPart.ToXml(writer);
282 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); 281 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
283 282
284 lock (sceneObject.Children) 283 SceneObjectPart[] parts = sceneObject.Parts;
284 for (int i = 0; i < parts.Length; i++)
285 { 285 {
286 foreach (SceneObjectPart part in sceneObject.Children.Values) 286 SceneObjectPart part = parts[i];
287 { 287 if (part.UUID != sceneObject.RootPart.UUID)
288 if (part.UUID != sceneObject.RootPart.UUID) 288 part.ToXml(writer);
289 {
290 part.ToXml(writer);
291 }
292 }
293 } 289 }
294 290
295 writer.WriteEndElement(); // End of OtherParts 291 writer.WriteEndElement(); // End of OtherParts
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index 7d9a6a9..9244bc3 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
68 SceneObjectGroup dupeSo 68 SceneObjectGroup dupeSo
69 = scene.SceneGraph.DuplicateObject( 69 = scene.SceneGraph.DuplicateObject(
70 part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity); 70 part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity);
71 Assert.That(dupeSo.Children.Count, Is.EqualTo(2)); 71 Assert.That(dupeSo.Parts.Length, Is.EqualTo(2));
72 72
73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1); 73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1);
74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2); 74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 60824be..f57cf98 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
81 // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since 81 // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since
82 // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. 82 // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed.
83 Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link."); 83 Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link.");
84 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained children after delink."); 84 Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained children after delink.");
85 Assert.That(grp1.Children.Count == 2); 85 Assert.That(grp1.Parts.Length == 2);
86 86
87 if (debugtest) 87 if (debugtest)
88 { 88 {
89 m_log.Debug("parts: " + grp1.Children.Count); 89 m_log.Debug("parts: " + grp1.Parts.Length);
90 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); 90 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
91 m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset); 91 m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset);
92 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset); 92 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset);
@@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
126 if (debugtest) 126 if (debugtest)
127 m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset); 127 m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset);
128 128
129 Assert.That(grp1.Children.Count, Is.EqualTo(1), "Group 1 still contained part2 after delink."); 129 Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
130 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); 130 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero");
131 } 131 }
132 132
@@ -177,22 +177,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests
177 grp3.LinkToGroup(grp4); 177 grp3.LinkToGroup(grp4);
178 178
179 // At this point we should have 4 parts total in two groups. 179 // At this point we should have 4 parts total in two groups.
180 Assert.That(grp1.Children.Count == 2, "Group1 children count should be 2"); 180 Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2");
181 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link."); 181 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link.");
182 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained parts after delink."); 182 Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained parts after delink.");
183 Assert.That(grp3.Children.Count == 2, "Group3 children count should be 2"); 183 Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2");
184 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link."); 184 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link.");
185 Assert.That(grp4.Children.Count, Is.EqualTo(0), "Group 4 still contained parts after delink."); 185 Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink.");
186 186
187 if (debugtest) 187 if (debugtest)
188 { 188 {
189 m_log.Debug("--------After Link-------"); 189 m_log.Debug("--------After Link-------");
190 m_log.Debug("Group1: parts:" + grp1.Children.Count); 190 m_log.Debug("Group1: parts:" + grp1.Parts.Length);
191 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); 191 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
192 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); 192 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
193 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset); 193 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset);
194 194
195 m_log.Debug("Group3: parts:"+grp3.Children.Count); 195 m_log.Debug("Group3: parts:" + grp3.Parts.Length);
196 m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation); 196 m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation);
197 m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset); 197 m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset);
198 m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset); 198 m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset);
@@ -240,12 +240,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
240 if (debugtest) 240 if (debugtest)
241 { 241 {
242 m_log.Debug("--------After De-Link-------"); 242 m_log.Debug("--------After De-Link-------");
243 m_log.Debug("Group1: parts:" + grp1.Children.Count); 243 m_log.Debug("Group1: parts:" + grp1.Parts.Length);
244 m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation); 244 m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation);
245 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); 245 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
246 m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset); 246 m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset);
247 247
248 m_log.Debug("Group3: parts:" + grp3.Children.Count); 248 m_log.Debug("Group3: parts:" + grp3.Parts.Length);
249 m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation); 249 m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation);
250 m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset); 250 m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset);
251 m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset); 251 m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset);
@@ -295,9 +295,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
295 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 295 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
296 296
297 Assert.That(storedObjects.Count, Is.EqualTo(1)); 297 Assert.That(storedObjects.Count, Is.EqualTo(1));
298 Assert.That(storedObjects[0].Children.Count, Is.EqualTo(2)); 298 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2));
299 Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); 299 Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
300 Assert.That(storedObjects[0].Children.ContainsKey(linkPartUuid)); 300 Assert.That(storedObjects[0].ContainsPart(linkPartUuid));
301 } 301 }
302 302
303 /// <summary> 303 /// <summary>
@@ -338,8 +338,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
338 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 338 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
339 339
340 Assert.That(storedObjects.Count, Is.EqualTo(1)); 340 Assert.That(storedObjects.Count, Is.EqualTo(1));
341 Assert.That(storedObjects[0].Children.Count, Is.EqualTo(1)); 341 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(1));
342 Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); 342 Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
343 } 343 }
344 } 344 }
345} 345}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index e3965ce..65baa52 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -121,8 +121,11 @@ namespace OpenSim.Region.Framework.Scenes
121// m_log.DebugFormat( 121// m_log.DebugFormat(
122// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 122// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
123 123
124 foreach (SceneObjectPart part in sceneObject.GetParts()) 124 SceneObjectPart[] parts = sceneObject.Parts;
125 for (int i = 0; i < parts.Length; i++)
125 { 126 {
127 SceneObjectPart part = parts[i];
128
126// m_log.DebugFormat( 129// m_log.DebugFormat(
127// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); 130// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
128 131
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
index d21b652..7f64ebd 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
@@ -121,19 +121,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
121 continue; 121 continue;
122 temp = (SceneObjectGroup) currObj; 122 temp = (SceneObjectGroup) currObj;
123 123
124 lock (temp.Children) 124 if (m_CMEntityHash.ContainsKey(temp.UUID))
125 { 125 {
126 if (m_CMEntityHash.ContainsKey(temp.UUID)) 126 foreach (SceneObjectPart part in temp.Parts)
127 { 127 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
128 foreach (SceneObjectPart part in temp.Children.Values)
129 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
130 missingList.Add(part);
131 }
132 else //Entire group is missing from revision. (and is a new part in region)
133 {
134 foreach (SceneObjectPart part in temp.Children.Values)
135 missingList.Add(part); 128 missingList.Add(part);
136 } 129 }
130 else //Entire group is missing from revision. (and is a new part in region)
131 {
132 foreach (SceneObjectPart part in temp.Parts)
133 missingList.Add(part);
137 } 134 }
138 } 135 }
139 return missingList; 136 return missingList;
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
index 0b02a9f..3a6996e 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
@@ -167,11 +167,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
167 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) 167 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
168 { 168 {
169 // Deal with new parts not revisioned that have been deleted. 169 // Deal with new parts not revisioned that have been deleted.
170 lock (group.Children) 170 SceneObjectPart[] parts = group.Parts;
171 for (int i = 0; i < parts.Length; i++)
171 { 172 {
172 foreach (SceneObjectPart part in group.Children.Values) 173 if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID))
173 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 174 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID);
174 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
175 } 175 }
176 } 176 }
177 177
@@ -210,12 +210,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
210 { 210 {
211 temp = SceneObjectSerializer.FromXml2Format(xml); 211 temp = SceneObjectSerializer.FromXml2Format(xml);
212 temp.SetScene(scene); 212 temp.SetScene(scene);
213 213
214 lock (temp.Children) 214 SceneObjectPart[] parts = temp.Parts;
215 { 215 for (int i = 0; i < parts.Length; i++)
216 foreach (SceneObjectPart part in temp.Children.Values) 216 parts[i].RegionHandle = scene.RegionInfo.RegionHandle;
217 part.RegionHandle = scene.RegionInfo.RegionHandle;
218 }
219 217
220 ReplacementList.Add(temp.UUID, (EntityBase)temp); 218 ReplacementList.Add(temp.UUID, (EntityBase)temp);
221 } 219 }
@@ -346,17 +344,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
346 System.Collections.ArrayList auraList = new System.Collections.ArrayList(); 344 System.Collections.ArrayList auraList = new System.Collections.ArrayList();
347 if (group == null) 345 if (group == null)
348 return null; 346 return null;
349 347
350 lock (group.Children) 348 SceneObjectPart[] parts = group.Parts;
349 for (int i = 0; i < parts.Length; i++)
351 { 350 {
352 foreach (SceneObjectPart part in group.Children.Values) 351 SceneObjectPart part = parts[i];
352 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
353 { 353 {
354 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 354 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale);
355 { 355 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
356 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); 356 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
357 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
358 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
359 }
360 } 357 }
361 } 358 }
362 359
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
index f75f40a..3807ccd 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
@@ -186,12 +186,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
186 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); 186 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
187 187
188 // Deal with new parts not revisioned that have been deleted. 188 // Deal with new parts not revisioned that have been deleted.
189 lock (group.Children) 189 foreach (SceneObjectPart part in group.Parts)
190 { 190 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
191 foreach (SceneObjectPart part in group.Children.Values) 191 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
192 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
193 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
194 }
195 } 192 }
196 193
197 public void SendMetaEntitiesToNewClient(IClientAPI client) 194 public void SendMetaEntitiesToNewClient(IClientAPI client)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
index 49d20e1..0248f36 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
@@ -132,33 +132,30 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
132 // if group is not contained in scene's list 132 // if group is not contained in scene's list
133 if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) 133 if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
134 { 134 {
135 lock (m_UnchangedEntity.Children) 135 foreach (SceneObjectPart part in m_UnchangedEntity.Parts)
136 { 136 {
137 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 137 // if scene list no longer contains this part, display translucent part and mark with red aura
138 if (!ContainsKey(sceneEntityList, part.UUID))
138 { 139 {
139 // if scene list no longer contains this part, display translucent part and mark with red aura 140 // if already displaying a red aura over part, make sure its red
140 if (!ContainsKey(sceneEntityList, part.UUID)) 141 if (m_AuraEntities.ContainsKey(part.UUID))
141 { 142 {
142 // if already displaying a red aura over part, make sure its red 143 m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale);
143 if (m_AuraEntities.ContainsKey(part.UUID)) 144 }
144 { 145 else
145 m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); 146 {
146 } 147 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
147 else 148 part.GetWorldPosition(),
148 { 149 MetaEntity.TRANSLUCENT,
149 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 150 new Vector3(254, 0, 0),
150 part.GetWorldPosition(), 151 part.Scale
151 MetaEntity.TRANSLUCENT, 152 );
152 new Vector3(254,0,0), 153 m_AuraEntities.Add(part.UUID, auraGroup);
153 part.Scale
154 );
155 m_AuraEntities.Add(part.UUID, auraGroup);
156 }
157 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
158 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
159 } 154 }
160 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id 155 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
156 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
161 } 157 }
158 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
162 } 159 }
163 160
164 // a deleted part has no where to point a beam particle system, 161 // a deleted part has no where to point a beam particle system,
@@ -183,11 +180,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
183 /// </summary> 180 /// </summary>
184 public bool HasChildPrim(UUID uuid) 181 public bool HasChildPrim(UUID uuid)
185 { 182 {
186 lock (m_UnchangedEntity.Children) 183 return m_UnchangedEntity.ContainsPart(uuid);
187 if (m_UnchangedEntity.Children.ContainsKey(uuid))
188 return true;
189
190 return false;
191 } 184 }
192 185
193 /// <summary> 186 /// <summary>
@@ -195,12 +188,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
195 /// </summary> 188 /// </summary>
196 public bool HasChildPrim(uint localID) 189 public bool HasChildPrim(uint localID)
197 { 190 {
198 lock (m_UnchangedEntity.Children) 191 foreach (SceneObjectPart part in m_UnchangedEntity.Parts)
199 { 192 if (part.LocalId == localID)
200 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 193 return true;
201 if (part.LocalId == localID)
202 return true;
203 }
204 194
205 return false; 195 return false;
206 } 196 }
@@ -237,72 +227,37 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
237 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user 227 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
238 // had originally saved. 228 // had originally saved.
239 // m_Entity will NOT necessarily be the same entity as the user had saved. 229 // m_Entity will NOT necessarily be the same entity as the user had saved.
240 lock (m_UnchangedEntity.Children) 230 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts)
241 { 231 {
242 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) 232 //This is the part that we use to show changes.
233 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
234 if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID))
243 { 235 {
244 //This is the part that we use to show changes. 236 sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID);
245 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); 237 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
246 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) 238 if (differences != Diff.NONE)
239 metaEntityPart.Text = "CHANGE: " + differences.ToString();
240 if (differences != 0)
247 { 241 {
248 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; 242 // Root Part that has been modified
249 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); 243 if ((differences & Diff.POSITION) > 0)
250 if (differences != Diff.NONE)
251 metaEntityPart.Text = "CHANGE: " + differences.ToString();
252 if (differences != 0)
253 {
254 // Root Part that has been modified
255 if ((differences&Diff.POSITION) > 0)
256 {
257 // If the position of any part has changed, make sure the RootPart of the
258 // meta entity is pointing with a beam particle system
259 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
260 {
261 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
262 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
263 }
264 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
265 m_UnchangedEntity.RootPart.GetWorldPosition(),
266 MetaEntity.TRANSLUCENT,
267 sceneEntityPart,
268 new Vector3(0,0,254)
269 );
270 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
271 }
272
273 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
274 {
275 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
276 m_AuraEntities.Remove(UnchangedPart.UUID);
277 }
278 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
279 UnchangedPart.GetWorldPosition(),
280 MetaEntity.TRANSLUCENT,
281 new Vector3(0,0,254),
282 UnchangedPart.Scale
283 );
284 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
285 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
286
287 DiffersFromSceneGroup = true;
288 }
289 else // no differences between scene part and meta part
290 { 244 {
245 // If the position of any part has changed, make sure the RootPart of the
246 // meta entity is pointing with a beam particle system
291 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) 247 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
292 { 248 {
293 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); 249 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
294 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); 250 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
295 } 251 }
296 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) 252 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
297 { 253 m_UnchangedEntity.RootPart.GetWorldPosition(),
298 m_AuraEntities[UnchangedPart.UUID].HideFromAll(); 254 MetaEntity.TRANSLUCENT,
299 m_AuraEntities.Remove(UnchangedPart.UUID); 255 sceneEntityPart,
300 } 256 new Vector3(0, 0, 254)
301 SetPartTransparency(metaEntityPart, MetaEntity.NONE); 257 );
258 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
302 } 259 }
303 } 260
304 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
305 {
306 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) 261 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
307 { 262 {
308 m_AuraEntities[UnchangedPart.UUID].HideFromAll(); 263 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
@@ -311,14 +266,46 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
311 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 266 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
312 UnchangedPart.GetWorldPosition(), 267 UnchangedPart.GetWorldPosition(),
313 MetaEntity.TRANSLUCENT, 268 MetaEntity.TRANSLUCENT,
314 new Vector3(254,0,0), 269 new Vector3(0, 0, 254),
315 UnchangedPart.Scale 270 UnchangedPart.Scale
316 ); 271 );
317 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); 272 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
318 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); 273 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
319 274
320 DiffersFromSceneGroup = true; 275 DiffersFromSceneGroup = true;
321 } 276 }
277 else // no differences between scene part and meta part
278 {
279 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
280 {
281 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
282 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
283 }
284 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
285 {
286 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
287 m_AuraEntities.Remove(UnchangedPart.UUID);
288 }
289 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
290 }
291 }
292 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
293 {
294 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
295 {
296 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
297 m_AuraEntities.Remove(UnchangedPart.UUID);
298 }
299 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
300 UnchangedPart.GetWorldPosition(),
301 MetaEntity.TRANSLUCENT,
302 new Vector3(254, 0, 0),
303 UnchangedPart.Scale
304 );
305 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
306 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
307
308 DiffersFromSceneGroup = true;
322 } 309 }
323 } 310 }
324 311
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index d7838c5..c7b1ed7 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -98,10 +98,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
98 98
99 #region Public Properties 99 #region Public Properties
100 100
101 public Dictionary<UUID, SceneObjectPart> Children 101 public SceneObjectPart[] Parts
102 { 102 {
103 get { return m_Entity.Children; } 103 get { return m_Entity.Parts; }
104 set { m_Entity.Children = value; }
105 } 104 }
106 105
107 public uint LocalId 106 public uint LocalId
@@ -150,19 +149,17 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
150 { 149 {
151 //make new uuids 150 //make new uuids
152 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>(); 151 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>();
153 152
154 lock (m_Entity.Children) 153 foreach (SceneObjectPart part in m_Entity.Parts)
155 { 154 {
156 foreach (SceneObjectPart part in m_Entity.Children.Values) 155 part.ResetIDs(part.LinkNum);
157 { 156 parts.Add(part.UUID, part);
158 part.ResetIDs(part.LinkNum);
159 parts.Add(part.UUID, part);
160 }
161
162 //finalize
163 m_Entity.RootPart.PhysActor = null;
164 m_Entity.Children = parts;
165 } 157 }
158
159 //finalize
160 m_Entity.RootPart.PhysActor = null;
161 foreach (SceneObjectPart part in parts.Values)
162 m_Entity.AddPart(part);
166 } 163 }
167 164
168 #endregion Protected Methods 165 #endregion Protected Methods
@@ -177,11 +174,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
177 //This deletes the group without removing from any databases. 174 //This deletes the group without removing from any databases.
178 //This is important because we are not IN any database. 175 //This is important because we are not IN any database.
179 //m_Entity.FakeDeleteGroup(); 176 //m_Entity.FakeDeleteGroup();
180 lock (m_Entity.Children) 177 foreach (SceneObjectPart part in m_Entity.Parts)
181 { 178 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
182 foreach (SceneObjectPart part in m_Entity.Children.Values)
183 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
184 }
185 } 179 }
186 180
187 /// <summary> 181 /// <summary>
@@ -189,15 +183,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
189 /// </summary> 183 /// </summary>
190 public virtual void HideFromAll() 184 public virtual void HideFromAll()
191 { 185 {
192 lock (m_Entity.Children) 186 foreach (SceneObjectPart part in m_Entity.Parts)
193 { 187 {
194 foreach (SceneObjectPart part in m_Entity.Children.Values) 188 m_Entity.Scene.ForEachClient(
195 { 189 delegate(IClientAPI controller)
196 m_Entity.Scene.ForEachClient( 190 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
197 delegate(IClientAPI controller) 191 );
198 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
199 );
200 }
201 } 192 }
202 } 193 }
203 194
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 59ad9d8..faed522 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
193 193
194 int i = 0; 194 int i = 0;
195 195
196 List<SceneObjectPart> partList = null; 196 foreach (SceneObjectPart part in my.ParentGroup.Parts)
197 lock (my.ParentGroup.Children)
198 partList = new List<SceneObjectPart>(my.ParentGroup.Children.Values);
199
200 foreach (SceneObjectPart part in partList)
201 { 197 {
202 rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security); 198 rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security);
203 } 199 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 0dd1787..caa39ba 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -294,8 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
294 case ScriptBaseClass.LINK_SET: 294 case ScriptBaseClass.LINK_SET:
295 if (m_host.ParentGroup != null) 295 if (m_host.ParentGroup != null)
296 { 296 {
297 lock (m_host.ParentGroup.Children) 297 return new List<SceneObjectPart>(m_host.ParentGroup.Parts);
298 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
299 } 298 }
300 return ret; 299 return ret;
301 300
@@ -312,8 +311,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
312 if (m_host.ParentGroup == null) 311 if (m_host.ParentGroup == null)
313 return new List<SceneObjectPart>(); 312 return new List<SceneObjectPart>();
314 313
315 lock (m_host.ParentGroup.Children) 314 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts);
316 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
317 315
318 if (ret.Contains(m_host)) 316 if (ret.Contains(m_host))
319 ret.Remove(m_host); 317 ret.Remove(m_host);
@@ -323,8 +321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
323 if (m_host.ParentGroup == null) 321 if (m_host.ParentGroup == null)
324 return new List<SceneObjectPart>(); 322 return new List<SceneObjectPart>();
325 323
326 lock (m_host.ParentGroup.Children) 324 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts);
327 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
328 325
329 if (ret.Contains(m_host.ParentGroup.RootPart)) 326 if (ret.Contains(m_host.ParentGroup.RootPart))
330 ret.Remove(m_host.ParentGroup.RootPart); 327 ret.Remove(m_host.ParentGroup.RootPart);
@@ -1281,16 +1278,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1281 if (group == null) 1278 if (group == null)
1282 return; 1279 return;
1283 bool allow = true; 1280 bool allow = true;
1284 1281
1285 lock (group.Children) 1282 foreach (SceneObjectPart part in group.Parts)
1286 { 1283 {
1287 foreach (SceneObjectPart part in group.Children.Values) 1284 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1288 { 1285 {
1289 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1286 allow = false;
1290 { 1287 break;
1291 allow = false;
1292 break;
1293 }
1294 } 1288 }
1295 } 1289 }
1296 1290
@@ -3889,18 +3883,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3889 case ScriptBaseClass.LINK_ALL_OTHERS: 3883 case ScriptBaseClass.LINK_ALL_OTHERS:
3890 case ScriptBaseClass.LINK_ALL_CHILDREN: 3884 case ScriptBaseClass.LINK_ALL_CHILDREN:
3891 case ScriptBaseClass.LINK_THIS: 3885 case ScriptBaseClass.LINK_THIS:
3892 lock (parentPrim.Children) 3886 foreach (SceneObjectPart part in parentPrim.Parts)
3893 { 3887 {
3894 foreach (SceneObjectPart part in parentPrim.Children.Values) 3888 if (part.UUID != m_host.UUID)
3895 { 3889 {
3896 if (part.UUID != m_host.UUID) 3890 childPrim = part;
3897 { 3891 break;
3898 childPrim = part;
3899 break;
3900 }
3901 } 3892 }
3902 break;
3903 } 3893 }
3894 break;
3904 default: 3895 default:
3905 childPrim = parentPrim.GetLinkNumPart(linknum); 3896 childPrim = parentPrim.GetLinkNumPart(linknum);
3906 if (childPrim.UUID == m_host.UUID) 3897 if (childPrim.UUID == m_host.UUID)
@@ -3911,7 +3902,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3911 if (linknum == ScriptBaseClass.LINK_ROOT) 3902 if (linknum == ScriptBaseClass.LINK_ROOT)
3912 { 3903 {
3913 // Restructuring Multiple Prims. 3904 // Restructuring Multiple Prims.
3914 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3905 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3915 parts.Remove(parentPrim.RootPart); 3906 parts.Remove(parentPrim.RootPart);
3916 if (parts.Count > 0) 3907 if (parts.Count > 0)
3917 { 3908 {
@@ -3976,19 +3967,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3976 if (parentPrim.RootPart.AttachmentPoint != 0) 3967 if (parentPrim.RootPart.AttachmentPoint != 0)
3977 return; // Fail silently if attached 3968 return; // Fail silently if attached
3978 3969
3979 lock (parentPrim.Children) 3970 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3971 parts.Remove(parentPrim.RootPart);
3972
3973 foreach (SceneObjectPart part in parts)
3980 { 3974 {
3981 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3975 parentPrim.DelinkFromGroup(part.LocalId, true);
3982 parts.Remove(parentPrim.RootPart); 3976 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3983
3984 foreach (SceneObjectPart part in parts)
3985 {
3986 parentPrim.DelinkFromGroup(part.LocalId, true);
3987 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3988 }
3989 parentPrim.HasGroupChanged = true;
3990 parentPrim.ScheduleGroupForFullUpdate();
3991 } 3977 }
3978 parentPrim.HasGroupChanged = true;
3979 parentPrim.ScheduleGroupForFullUpdate();
3992 } 3980 }
3993 3981
3994 public LSL_String llGetLinkKey(int linknum) 3982 public LSL_String llGetLinkKey(int linknum)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 41501f2..3575889 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -209,15 +209,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
209 else 209 else
210 Type = 0x02; // Passive 210 Type = 0x02; // Passive
211 211
212 lock (part.ParentGroup.Children) 212 foreach (SceneObjectPart p in part.ParentGroup.Parts)
213 { 213 {
214 foreach (SceneObjectPart p in part.ParentGroup.Children.Values) 214 if (p.Inventory.ContainsScripts())
215 { 215 {
216 if (p.Inventory.ContainsScripts()) 216 Type |= 0x08; // Scripted
217 { 217 break;
218 Type |= 0x08; // Scripted
219 break;
220 }
221 } 218 }
222 } 219 }
223 220
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index de6e815..2e5020b 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Data.Null
163 // We can't simply store groups here because on delinking, OpenSim will not update the original group 163 // We can't simply store groups here because on delinking, OpenSim will not update the original group
164 // directly. Rather, the newly delinked parts will be updated to be in their own scene object group 164 // directly. Rather, the newly delinked parts will be updated to be in their own scene object group
165 // Therefore, we need to store parts rather than groups. 165 // Therefore, we need to store parts rather than groups.
166 foreach (SceneObjectPart prim in obj.Children.Values) 166 foreach (SceneObjectPart prim in obj.Parts)
167 { 167 {
168 m_log.DebugFormat( 168 m_log.DebugFormat(
169 "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}", 169 "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}",
diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
index b47ad5d..fc44358 100644
--- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Tests.Common.Mock
84 84
85 public List<InventoryItemBase> getInventoryInFolder(UUID folderID) 85 public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
86 { 86 {
87 InventoryFolderBase folder = m_folders[folderID]; 87// InventoryFolderBase folder = m_folders[folderID];
88 88
89// m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0} {1}", folder.Name, folder.ID); 89// m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0} {1}", folder.Name, folder.ID);
90 90
@@ -116,7 +116,7 @@ namespace OpenSim.Tests.Common.Mock
116 116
117 public List<InventoryFolderBase> getInventoryFolders(UUID parentID) 117 public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
118 { 118 {
119 InventoryFolderBase parentFolder = m_folders[parentID]; 119// InventoryFolderBase parentFolder = m_folders[parentID];
120 120
121// m_log.DebugFormat("[MOCK INV DB]: Getting folders in folder {0} {1}", parentFolder.Name, parentFolder.ID); 121// m_log.DebugFormat("[MOCK INV DB]: Getting folders in folder {0} {1}", parentFolder.Name, parentFolder.ID);
122 122
@@ -185,7 +185,7 @@ namespace OpenSim.Tests.Common.Mock
185 185
186 public void addInventoryItem(InventoryItemBase item) 186 public void addInventoryItem(InventoryItemBase item)
187 { 187 {
188 InventoryFolderBase folder = m_folders[item.Folder]; 188// InventoryFolderBase folder = m_folders[item.Folder];
189 189
190// m_log.DebugFormat( 190// m_log.DebugFormat(
191// "[MOCK INV DB]: Adding inventory item {0} {1} in {2} {3}", item.Name, item.ID, folder.Name, folder.ID); 191// "[MOCK INV DB]: Adding inventory item {0} {1} in {2} {3}", item.Name, item.ID, folder.Name, folder.ID);