aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs55
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs512
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs131
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.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.cs173
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs38
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs100
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs11
19 files changed, 739 insertions, 586 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 365cdbb..847a999 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -406,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
406 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 406 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
407 { 407 {
408 if (!m_scene.Permissions.CanRezObject( 408 if (!m_scene.Permissions.CanRezObject(
409 part.ParentGroup.Children.Count, remoteClient.AgentId, presence.AbsolutePosition)) 409 part.ParentGroup.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
410 return; 410 return;
411 411
412 presence.Appearance.DetachAttachment(itemID); 412 presence.Appearance.DetachAttachment(itemID);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index eef0c73..6decf54 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -526,7 +526,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
526 group.RootPart.CreateSelected = true; 526 group.RootPart.CreateSelected = true;
527 527
528 if (!m_Scene.Permissions.CanRezObject( 528 if (!m_Scene.Permissions.CanRezObject(
529 group.Children.Count, remoteClient.AgentId, pos) 529 group.PrimCount, remoteClient.AgentId, pos)
530 && !attachment) 530 && !attachment)
531 { 531 {
532 // The client operates in no fail mode. It will 532 // The client operates in no fail mode. It will
@@ -594,7 +594,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
594 rootPart.Name = item.Name; 594 rootPart.Name = item.Name;
595 rootPart.Description = item.Description; 595 rootPart.Description = item.Description;
596 596
597 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); 597 List<SceneObjectPart> partList = null;
598 lock (group.Children)
599 partList = new List<SceneObjectPart>(group.Children.Values);
598 600
599 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 601 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
600 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) 602 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index bc653ce..1623e6e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -243,36 +243,39 @@ 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 foreach (SceneObjectPart part in sceneObject.Children.Values) 246 lock (sceneObject.Children)
247 { 247 {
248 if (!ResolveUserUuid(part.CreatorID)) 248 foreach (SceneObjectPart part in sceneObject.Children.Values)
249 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
250
251 if (!ResolveUserUuid(part.OwnerID))
252 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
253
254 if (!ResolveUserUuid(part.LastOwnerID))
255 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
256
257 // And zap any troublesome sit target information
258 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
259 part.SitTargetPosition = new Vector3(0, 0, 0);
260
261 // Fix ownership/creator of inventory items
262 // Not doing so results in inventory items
263 // being no copy/no mod for everyone
264 lock (part.TaskInventory)
265 { 249 {
266 TaskInventoryDictionary inv = part.TaskInventory; 250 if (!ResolveUserUuid(part.CreatorID))
267 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 251 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
252
253 if (!ResolveUserUuid(part.OwnerID))
254 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
255
256 if (!ResolveUserUuid(part.LastOwnerID))
257 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
258
259 // And zap any troublesome sit target information
260 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
261 part.SitTargetPosition = new Vector3(0, 0, 0);
262
263 // Fix ownership/creator of inventory items
264 // Not doing so results in inventory items
265 // being no copy/no mod for everyone
266 lock (part.TaskInventory)
268 { 267 {
269 if (!ResolveUserUuid(kvp.Value.OwnerID)) 268 TaskInventoryDictionary inv = part.TaskInventory;
270 { 269 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
271 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
272 }
273 if (!ResolveUserUuid(kvp.Value.CreatorID))
274 { 270 {
275 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 271 if (!ResolveUserUuid(kvp.Value.OwnerID))
272 {
273 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
274 }
275 if (!ResolveUserUuid(kvp.Value.CreatorID))
276 {
277 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
278 }
276 } 279 }
277 } 280 }
278 } 281 }
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 62abd4c..8ce6daf 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -128,7 +128,10 @@ 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 = new List<SceneObjectPart>(group.Children.Values); 131 List<SceneObjectPart> partList = null;
132
133 lock (group.Children)
134 partList = new List<SceneObjectPart>(group.Children.Values);
132 135
133 if (m_scene.Permissions.PropagatePermissions()) 136 if (m_scene.Permissions.PropagatePermissions())
134 { 137 {
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
index b96d95a..2f70c0a 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
@@ -227,277 +227,281 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
227 { 227 {
228 SceneObjectGroup mapdot = (SceneObjectGroup)obj; 228 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
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 // Loop over prim in group 231 // Loop over prim in group
231 foreach (SceneObjectPart part in mapdot.Children.Values) 232 lock (mapdot.Children)
232 { 233 {
233 if (part == null) 234 foreach (SceneObjectPart part in mapdot.Children.Values)
234 continue;
235
236 // Draw if the object is at least 1 meter wide in any direction
237 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
238 { 235 {
239 // Try to get the RGBA of the default texture entry.. 236 if (part == null)
240 // 237 continue;
241 try 238
239 // Draw if the object is at least 1 meter wide in any direction
240 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
242 { 241 {
243 // get the null checks out of the way 242 // Try to get the RGBA of the default texture entry..
244 // skip the ones that break 243 //
245 if (part == null) 244 try
246 continue;
247
248 if (part.Shape == null)
249 continue;
250
251 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
252 continue; // eliminates trees from this since we don't really have a good tree representation
253 // if you want tree blocks on the map comment the above line and uncomment the below line
254 //mapdotspot = Color.PaleGreen;
255
256 Primitive.TextureEntry textureEntry = part.Shape.Textures;
257
258 if (textureEntry == null || textureEntry.DefaultTexture == null)
259 continue;
260
261 Color4 texcolor = textureEntry.DefaultTexture.RGBA;
262
263 // Not sure why some of these are null, oh well.
264
265 int colorr = 255 - (int)(texcolor.R * 255f);
266 int colorg = 255 - (int)(texcolor.G * 255f);
267 int colorb = 255 - (int)(texcolor.B * 255f);
268
269 if (!(colorr == 255 && colorg == 255 && colorb == 255))
270 { 245 {
271 //Try to set the map spot color 246 // get the null checks out of the way
272 try 247 // skip the ones that break
273 { 248 if (part == null)
274 // If the color gets goofy somehow, skip it *shakes fist at Color4 249 continue;
275 mapdotspot = Color.FromArgb(colorr, colorg, colorb); 250
276 } 251 if (part.Shape == null)
277 catch (ArgumentException) 252 continue;
253
254 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
255 continue; // eliminates trees from this since we don't really have a good tree representation
256 // if you want tree blocks on the map comment the above line and uncomment the below line
257 //mapdotspot = Color.PaleGreen;
258
259 Primitive.TextureEntry textureEntry = part.Shape.Textures;
260
261 if (textureEntry == null || textureEntry.DefaultTexture == null)
262 continue;
263
264 Color4 texcolor = textureEntry.DefaultTexture.RGBA;
265
266 // Not sure why some of these are null, oh well.
267
268 int colorr = 255 - (int)(texcolor.R * 255f);
269 int colorg = 255 - (int)(texcolor.G * 255f);
270 int colorb = 255 - (int)(texcolor.B * 255f);
271
272 if (!(colorr == 255 && colorg == 255 && colorb == 255))
278 { 273 {
274 //Try to set the map spot color
275 try
276 {
277 // If the color gets goofy somehow, skip it *shakes fist at Color4
278 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
279 }
280 catch (ArgumentException)
281 {
282 }
279 } 283 }
280 } 284 }
281 } 285 catch (IndexOutOfRangeException)
282 catch (IndexOutOfRangeException) 286 {
283 { 287 // Windows Array
284 // Windows Array 288 }
285 } 289 catch (ArgumentOutOfRangeException)
286 catch (ArgumentOutOfRangeException) 290 {
287 { 291 // Mono Array
288 // Mono Array 292 }
289 } 293
290 294 Vector3 pos = part.GetWorldPosition();
291 Vector3 pos = part.GetWorldPosition(); 295
292 296 // skip prim outside of retion
293 // skip prim outside of retion 297 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
294 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
295 continue;
296
297 // skip prim in non-finite position
298 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
299 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
300 continue;
301
302 // Figure out if object is under 256m above the height of the terrain
303 bool isBelow256AboveTerrain = false;
304
305 try
306 {
307 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
308 }
309 catch (Exception)
310 {
311 }
312
313 if (isBelow256AboveTerrain)
314 {
315 // Translate scale by rotation so scale is represented properly when object is rotated
316 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
317 Vector3 scale = new Vector3();
318 Vector3 tScale = new Vector3();
319 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
320
321 Quaternion llrot = part.GetWorldRotation();
322 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
323 scale = lscale * rot;
324
325 // negative scales don't work in this situation
326 scale.X = Math.Abs(scale.X);
327 scale.Y = Math.Abs(scale.Y);
328 scale.Z = Math.Abs(scale.Z);
329
330 // This scaling isn't very accurate and doesn't take into account the face rotation :P
331 int mapdrawstartX = (int)(pos.X - scale.X);
332 int mapdrawstartY = (int)(pos.Y - scale.Y);
333 int mapdrawendX = (int)(pos.X + scale.X);
334 int mapdrawendY = (int)(pos.Y + scale.Y);
335
336 // If object is beyond the edge of the map, don't draw it to avoid errors
337 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
338 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
339 || mapdrawendY > ((int)Constants.RegionSize - 1))
340 continue; 298 continue;
341 299
342#region obb face reconstruction part duex 300 // skip prim in non-finite position
343 Vector3[] vertexes = new Vector3[8]; 301 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
344 302 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
345 // float[] distance = new float[6]; 303 continue;
346 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei 304
347 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei 305 // Figure out if object is under 256m above the height of the terrain
348 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei 306 bool isBelow256AboveTerrain = false;
349 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei 307
350 308 try
351 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
352 scale = ((tScale * rot));
353 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
354 // vertexes[0].x = pos.X + vertexes[0].x;
355 //vertexes[0].y = pos.Y + vertexes[0].y;
356 //vertexes[0].z = pos.Z + vertexes[0].z;
357
358 FaceA[0] = vertexes[0];
359 FaceB[3] = vertexes[0];
360 FaceA[4] = vertexes[0];
361
362 tScale = lscale;
363 scale = ((tScale * rot));
364 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
365
366 // vertexes[1].x = pos.X + vertexes[1].x;
367 // vertexes[1].y = pos.Y + vertexes[1].y;
368 //vertexes[1].z = pos.Z + vertexes[1].z;
369
370 FaceB[0] = vertexes[1];
371 FaceA[1] = vertexes[1];
372 FaceC[4] = vertexes[1];
373
374 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
375 scale = ((tScale * rot));
376
377 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
378
379 //vertexes[2].x = pos.X + vertexes[2].x;
380 //vertexes[2].y = pos.Y + vertexes[2].y;
381 //vertexes[2].z = pos.Z + vertexes[2].z;
382
383 FaceC[0] = vertexes[2];
384 FaceD[3] = vertexes[2];
385 FaceC[5] = vertexes[2];
386
387 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
388 scale = ((tScale * rot));
389 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
390
391 //vertexes[3].x = pos.X + vertexes[3].x;
392 // vertexes[3].y = pos.Y + vertexes[3].y;
393 // vertexes[3].z = pos.Z + vertexes[3].z;
394
395 FaceD[0] = vertexes[3];
396 FaceC[1] = vertexes[3];
397 FaceA[5] = vertexes[3];
398
399 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
400 scale = ((tScale * rot));
401 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
402
403 // vertexes[4].x = pos.X + vertexes[4].x;
404 // vertexes[4].y = pos.Y + vertexes[4].y;
405 // vertexes[4].z = pos.Z + vertexes[4].z;
406
407 FaceB[1] = vertexes[4];
408 FaceA[2] = vertexes[4];
409 FaceD[4] = vertexes[4];
410
411 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
412 scale = ((tScale * rot));
413 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
414
415 // vertexes[5].x = pos.X + vertexes[5].x;
416 // vertexes[5].y = pos.Y + vertexes[5].y;
417 // vertexes[5].z = pos.Z + vertexes[5].z;
418
419 FaceD[1] = vertexes[5];
420 FaceC[2] = vertexes[5];
421 FaceB[5] = vertexes[5];
422
423 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
424 scale = ((tScale * rot));
425 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
426
427 // vertexes[6].x = pos.X + vertexes[6].x;
428 // vertexes[6].y = pos.Y + vertexes[6].y;
429 // vertexes[6].z = pos.Z + vertexes[6].z;
430
431 FaceB[2] = vertexes[6];
432 FaceA[3] = vertexes[6];
433 FaceB[4] = vertexes[6];
434
435 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
436 scale = ((tScale * rot));
437 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
438
439 // vertexes[7].x = pos.X + vertexes[7].x;
440 // vertexes[7].y = pos.Y + vertexes[7].y;
441 // vertexes[7].z = pos.Z + vertexes[7].z;
442
443 FaceD[2] = vertexes[7];
444 FaceC[3] = vertexes[7];
445 FaceD[5] = vertexes[7];
446#endregion
447
448 //int wy = 0;
449
450 //bool breakYN = false; // If we run into an error drawing, break out of the
451 // loop so we don't lag to death on error handling
452 DrawStruct ds = new DrawStruct();
453 ds.brush = new SolidBrush(mapdotspot);
454 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
455
456 ds.trns = new face[FaceA.Length];
457
458 for (int i = 0; i < FaceA.Length; i++)
459 { 309 {
460 Point[] working = new Point[5]; 310 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
461 working[0] = project(FaceA[i], axPos);
462 working[1] = project(FaceB[i], axPos);
463 working[2] = project(FaceD[i], axPos);
464 working[3] = project(FaceC[i], axPos);
465 working[4] = project(FaceA[i], axPos);
466
467 face workingface = new face();
468 workingface.pts = working;
469
470 ds.trns[i] = workingface;
471 } 311 }
472 312 catch (Exception)
473 z_sort.Add(part.LocalId, ds); 313 {
474 z_localIDs.Add(part.LocalId); 314 }
475 z_sortheights.Add(pos.Z); 315
476 316 if (isBelow256AboveTerrain)
477 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) 317 {
478 //{ 318 // Translate scale by rotation so scale is represented properly when object is rotated
479 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++) 319 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
320 Vector3 scale = new Vector3();
321 Vector3 tScale = new Vector3();
322 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
323
324 Quaternion llrot = part.GetWorldRotation();
325 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
326 scale = lscale * rot;
327
328 // negative scales don't work in this situation
329 scale.X = Math.Abs(scale.X);
330 scale.Y = Math.Abs(scale.Y);
331 scale.Z = Math.Abs(scale.Z);
332
333 // This scaling isn't very accurate and doesn't take into account the face rotation :P
334 int mapdrawstartX = (int)(pos.X - scale.X);
335 int mapdrawstartY = (int)(pos.Y - scale.Y);
336 int mapdrawendX = (int)(pos.X + scale.X);
337 int mapdrawendY = (int)(pos.Y + scale.Y);
338
339 // If object is beyond the edge of the map, don't draw it to avoid errors
340 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
341 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
342 || mapdrawendY > ((int)Constants.RegionSize - 1))
343 continue;
344
345 #region obb face reconstruction part duex
346 Vector3[] vertexes = new Vector3[8];
347
348 // float[] distance = new float[6];
349 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
350 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
351 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
352 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
353
354 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
355 scale = ((tScale * rot));
356 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
357 // vertexes[0].x = pos.X + vertexes[0].x;
358 //vertexes[0].y = pos.Y + vertexes[0].y;
359 //vertexes[0].z = pos.Z + vertexes[0].z;
360
361 FaceA[0] = vertexes[0];
362 FaceB[3] = vertexes[0];
363 FaceA[4] = vertexes[0];
364
365 tScale = lscale;
366 scale = ((tScale * rot));
367 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
368
369 // vertexes[1].x = pos.X + vertexes[1].x;
370 // vertexes[1].y = pos.Y + vertexes[1].y;
371 //vertexes[1].z = pos.Z + vertexes[1].z;
372
373 FaceB[0] = vertexes[1];
374 FaceA[1] = vertexes[1];
375 FaceC[4] = vertexes[1];
376
377 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
378 scale = ((tScale * rot));
379
380 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
381
382 //vertexes[2].x = pos.X + vertexes[2].x;
383 //vertexes[2].y = pos.Y + vertexes[2].y;
384 //vertexes[2].z = pos.Z + vertexes[2].z;
385
386 FaceC[0] = vertexes[2];
387 FaceD[3] = vertexes[2];
388 FaceC[5] = vertexes[2];
389
390 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
391 scale = ((tScale * rot));
392 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
393
394 //vertexes[3].x = pos.X + vertexes[3].x;
395 // vertexes[3].y = pos.Y + vertexes[3].y;
396 // vertexes[3].z = pos.Z + vertexes[3].z;
397
398 FaceD[0] = vertexes[3];
399 FaceC[1] = vertexes[3];
400 FaceA[5] = vertexes[3];
401
402 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
403 scale = ((tScale * rot));
404 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
405
406 // vertexes[4].x = pos.X + vertexes[4].x;
407 // vertexes[4].y = pos.Y + vertexes[4].y;
408 // vertexes[4].z = pos.Z + vertexes[4].z;
409
410 FaceB[1] = vertexes[4];
411 FaceA[2] = vertexes[4];
412 FaceD[4] = vertexes[4];
413
414 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
415 scale = ((tScale * rot));
416 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
417
418 // vertexes[5].x = pos.X + vertexes[5].x;
419 // vertexes[5].y = pos.Y + vertexes[5].y;
420 // vertexes[5].z = pos.Z + vertexes[5].z;
421
422 FaceD[1] = vertexes[5];
423 FaceC[2] = vertexes[5];
424 FaceB[5] = vertexes[5];
425
426 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
427 scale = ((tScale * rot));
428 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
429
430 // vertexes[6].x = pos.X + vertexes[6].x;
431 // vertexes[6].y = pos.Y + vertexes[6].y;
432 // vertexes[6].z = pos.Z + vertexes[6].z;
433
434 FaceB[2] = vertexes[6];
435 FaceA[3] = vertexes[6];
436 FaceB[4] = vertexes[6];
437
438 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
439 scale = ((tScale * rot));
440 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
441
442 // vertexes[7].x = pos.X + vertexes[7].x;
443 // vertexes[7].y = pos.Y + vertexes[7].y;
444 // vertexes[7].z = pos.Z + vertexes[7].z;
445
446 FaceD[2] = vertexes[7];
447 FaceC[3] = vertexes[7];
448 FaceD[5] = vertexes[7];
449 #endregion
450
451 //int wy = 0;
452
453 //bool breakYN = false; // If we run into an error drawing, break out of the
454 // loop so we don't lag to death on error handling
455 DrawStruct ds = new DrawStruct();
456 ds.brush = new SolidBrush(mapdotspot);
457 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
458
459 ds.trns = new face[FaceA.Length];
460
461 for (int i = 0; i < FaceA.Length; i++)
462 {
463 Point[] working = new Point[5];
464 working[0] = project(FaceA[i], axPos);
465 working[1] = project(FaceB[i], axPos);
466 working[2] = project(FaceD[i], axPos);
467 working[3] = project(FaceC[i], axPos);
468 working[4] = project(FaceA[i], axPos);
469
470 face workingface = new face();
471 workingface.pts = working;
472
473 ds.trns[i] = workingface;
474 }
475
476 z_sort.Add(part.LocalId, ds);
477 z_localIDs.Add(part.LocalId);
478 z_sortheights.Add(pos.Z);
479
480 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
480 //{ 481 //{
481 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); 482 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
482 //try
483 //{ 483 //{
484 // Remember, flip the y! 484 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
485 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot); 485 //try
486 //{
487 // Remember, flip the y!
488 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
489 //}
490 //catch (ArgumentException)
491 //{
492 // breakYN = true;
493 //}
494
495 //if (breakYN)
496 // break;
486 //} 497 //}
487 //catch (ArgumentException) 498
488 //{
489 // breakYN = true;
490 //}
491
492 //if (breakYN) 499 //if (breakYN)
493 // break; 500 // break;
494 //} 501 //}
495 502 } // Object is within 256m Z of terrain
496 //if (breakYN) 503 } // object is at least a meter wide
497 // break; 504 } // mapdot.Children lock
498 //}
499 } // Object is within 256m Z of terrain
500 } // object is at least a meter wide
501 } // loop over group children 505 } // loop over group children
502 } // entitybase is sceneobject group 506 } // entitybase is sceneobject group
503 } // foreach loop over entities 507 } // foreach loop over entities
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 9fef8f4..379128a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1974,7 +1974,7 @@ namespace OpenSim.Region.Framework.Scenes
1974 if (null == group) 1974 if (null == group)
1975 return null; 1975 return null;
1976 1976
1977 if (!Permissions.CanRezObject(group.Children.Count, item.OwnerID, pos)) 1977 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos))
1978 return null; 1978 return null;
1979 1979
1980 if (!Permissions.BypassPermissions()) 1980 if (!Permissions.BypassPermissions())
@@ -2051,8 +2051,11 @@ namespace OpenSim.Region.Framework.Scenes
2051 sog.SetGroup(groupID, remoteClient); 2051 sog.SetGroup(groupID, remoteClient);
2052 sog.ScheduleGroupForFullUpdate(); 2052 sog.ScheduleGroupForFullUpdate();
2053 2053
2054 foreach (SceneObjectPart child in sog.Children.Values) 2054 lock (sog.Children)
2055 child.Inventory.ChangeInventoryOwner(ownerID); 2055 {
2056 foreach (SceneObjectPart child in sog.Children.Values)
2057 child.Inventory.ChangeInventoryOwner(ownerID);
2058 }
2056 } 2059 }
2057 else 2060 else
2058 { 2061 {
@@ -2062,16 +2065,18 @@ namespace OpenSim.Region.Framework.Scenes
2062 if (sog.GroupID != groupID) 2065 if (sog.GroupID != groupID)
2063 continue; 2066 continue;
2064 2067
2065 foreach (SceneObjectPart child in sog.Children.Values) 2068 lock (sog.Children)
2066 { 2069 {
2067 child.LastOwnerID = child.OwnerID; 2070 foreach (SceneObjectPart child in sog.Children.Values)
2068 child.Inventory.ChangeInventoryOwner(groupID); 2071 {
2072 child.LastOwnerID = child.OwnerID;
2073 child.Inventory.ChangeInventoryOwner(groupID);
2074 }
2069 } 2075 }
2070 2076
2071 sog.SetOwnerId(groupID); 2077 sog.SetOwnerId(groupID);
2072 sog.ApplyNextOwnerPermissions(); 2078 sog.ApplyNextOwnerPermissions();
2073 } 2079 }
2074
2075 } 2080 }
2076 2081
2077 foreach (uint localID in localIDs) 2082 foreach (uint localID in localIDs)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e25b1f1..9f1575d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -156,21 +156,29 @@ namespace OpenSim.Region.Framework.Scenes
156 } 156 }
157 break; 157 break;
158 } 158 }
159 else 159 else
160 { 160 {
161 // We also need to check the children of this prim as they 161 // We also need to check the children of this prim as they
162 // can be selected as well and send property information 162 // can be selected as well and send property information
163 bool foundPrim = false; 163 bool foundPrim = false;
164 foreach (KeyValuePair<UUID, SceneObjectPart> child in ((SceneObjectGroup) ent).Children) 164
165 { 165 SceneObjectGroup sog = ent as SceneObjectGroup;
166 if (child.Value.LocalId == primLocalID) 166
167 { 167 lock (sog.Children)
168 child.Value.GetProperties(remoteClient); 168 {
169 foundPrim = true; 169 foreach (KeyValuePair<UUID, SceneObjectPart> child in (sog.Children))
170 break; 170 {
171 } 171 if (child.Value.LocalId == primLocalID)
172 } 172 {
173 if (foundPrim) break; 173 child.Value.GetProperties(remoteClient);
174 foundPrim = true;
175 break;
176 }
177 }
178 }
179
180 if (foundPrim)
181 break;
174 } 182 }
175 } 183 }
176 } 184 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b808c6d..8556105 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1756,8 +1756,9 @@ namespace OpenSim.Region.Framework.Scenes
1756 1756
1757 if (group.RootPart == null) 1757 if (group.RootPart == null)
1758 { 1758 {
1759 m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", 1759 m_log.ErrorFormat(
1760 group.Children == null ? 0 : group.Children.Count); 1760 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1761 group.Children == null ? 0 : group.PrimCount);
1761 } 1762 }
1762 1763
1763 AddRestoredSceneObject(group, true, true); 1764 AddRestoredSceneObject(group, true, true);
@@ -2064,18 +2065,22 @@ namespace OpenSim.Region.Framework.Scenes
2064 group.RemoveScriptInstances(true); 2065 group.RemoveScriptInstances(true);
2065 } 2066 }
2066 2067
2067 foreach (SceneObjectPart part in group.Children.Values) 2068 lock (group.Children)
2068 { 2069 {
2069 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2070 foreach (SceneObjectPart part in group.Children.Values)
2070 { 2071 {
2071 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2072 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2072 } 2073 {
2073 else if (part.PhysActor != null) 2074 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
2074 { 2075 }
2075 PhysicsScene.RemovePrim(part.PhysActor); 2076 else if (part.PhysActor != null)
2076 part.PhysActor = null; 2077 {
2078 PhysicsScene.RemovePrim(part.PhysActor);
2079 part.PhysActor = null;
2080 }
2077 } 2081 }
2078 } 2082 }
2083
2079// if (rootPart.PhysActor != null) 2084// if (rootPart.PhysActor != null)
2080// { 2085// {
2081// PhysicsScene.RemovePrim(rootPart.PhysActor); 2086// PhysicsScene.RemovePrim(rootPart.PhysActor);
@@ -2426,14 +2431,16 @@ namespace OpenSim.Region.Framework.Scenes
2426 2431
2427 // Force allocation of new LocalId 2432 // Force allocation of new LocalId
2428 // 2433 //
2429 foreach (SceneObjectPart p in sceneObject.Children.Values) 2434 lock (sceneObject.Children)
2430 p.LocalId = 0; 2435 {
2436 foreach (SceneObjectPart p in sceneObject.Children.Values)
2437 p.LocalId = 0;
2438 }
2431 2439
2432 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2440 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2433 { 2441 {
2434 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2442 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2435 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2443 sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2436
2437 2444
2438 // Don't sent a full update here because this will cause full updates to be sent twice for 2445 // Don't sent a full update here because this will cause full updates to be sent twice for
2439 // attachments on region crossings, resulting in viewer glitches. 2446 // attachments on region crossings, resulting in viewer glitches.
@@ -2447,7 +2454,6 @@ namespace OpenSim.Region.Framework.Scenes
2447 2454
2448 if (sp != null) 2455 if (sp != null)
2449 { 2456 {
2450
2451 SceneObjectGroup grp = sceneObject; 2457 SceneObjectGroup grp = sceneObject;
2452 2458
2453 m_log.DebugFormat( 2459 m_log.DebugFormat(
@@ -2459,7 +2465,6 @@ namespace OpenSim.Region.Framework.Scenes
2459 2465
2460 if (AttachmentsModule != null) 2466 if (AttachmentsModule != null)
2461 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2467 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2462
2463 } 2468 }
2464 else 2469 else
2465 { 2470 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 31faeec..2b24706 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -364,45 +364,48 @@ namespace OpenSim.Region.Framework.Scenes
364// "[SCENE GRAPH]: Adding object {0} {1} to region {2}", 364// "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
365// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); 365// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
366 366
367 if (m_parentScene.m_clampPrimSize) 367 lock (sceneObject.Children)
368 { 368 {
369 foreach (SceneObjectPart part in sceneObject.Children.Values) 369 if (m_parentScene.m_clampPrimSize)
370 { 370 {
371 Vector3 scale = part.Shape.Scale; 371 foreach (SceneObjectPart part in sceneObject.Children.Values)
372 372 {
373 if (scale.X > m_parentScene.m_maxNonphys) 373 Vector3 scale = part.Shape.Scale;
374 scale.X = m_parentScene.m_maxNonphys; 374
375 if (scale.Y > m_parentScene.m_maxNonphys) 375 if (scale.X > m_parentScene.m_maxNonphys)
376 scale.Y = m_parentScene.m_maxNonphys; 376 scale.X = m_parentScene.m_maxNonphys;
377 if (scale.Z > m_parentScene.m_maxNonphys) 377 if (scale.Y > m_parentScene.m_maxNonphys)
378 scale.Z = m_parentScene.m_maxNonphys; 378 scale.Y = m_parentScene.m_maxNonphys;
379 379 if (scale.Z > m_parentScene.m_maxNonphys)
380 part.Shape.Scale = scale; 380 scale.Z = m_parentScene.m_maxNonphys;
381
382 part.Shape.Scale = scale;
383 }
381 } 384 }
382 } 385
386 sceneObject.AttachToScene(m_parentScene);
387
388 if (sendClientUpdates)
389 sceneObject.ScheduleGroupForFullUpdate();
390
391 Entities.Add(sceneObject);
392 m_numPrim += sceneObject.Children.Count;
383 393
384 sceneObject.AttachToScene(m_parentScene); 394 if (attachToBackup)
395 sceneObject.AttachToBackup();
385 396
386 if (sendClientUpdates) 397 if (OnObjectCreate != null)
387 sceneObject.ScheduleGroupForFullUpdate(); 398 OnObjectCreate(sceneObject);
388 399
389 Entities.Add(sceneObject); 400 lock (m_dictionary_lock)
390 m_numPrim += sceneObject.Children.Count;
391
392 if (attachToBackup)
393 sceneObject.AttachToBackup();
394
395 if (OnObjectCreate != null)
396 OnObjectCreate(sceneObject);
397
398 lock (m_dictionary_lock)
399 {
400 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
401 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
402 foreach (SceneObjectPart part in sceneObject.Children.Values)
403 { 401 {
404 SceneObjectGroupsByFullID[part.UUID] = sceneObject; 402 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
405 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; 403 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
404 foreach (SceneObjectPart part in sceneObject.Children.Values)
405 {
406 SceneObjectGroupsByFullID[part.UUID] = sceneObject;
407 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
408 }
406 } 409 }
407 } 410 }
408 } 411 }
@@ -420,11 +423,16 @@ namespace OpenSim.Region.Framework.Scenes
420 { 423 {
421 if (!resultOfObjectLinked) 424 if (!resultOfObjectLinked)
422 { 425 {
423 m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; 426 SceneObjectGroup sog = Entities[uuid] as SceneObjectGroup;
424 427
425 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 428 lock (sog.Children)
426 { 429 {
427 RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count); 430 m_numPrim -= sog.PrimCount;
431
432 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
433 {
434 RemovePhysicalPrim(sog.PrimCount);
435 }
428 } 436 }
429 } 437 }
430 438
@@ -1603,7 +1611,7 @@ namespace OpenSim.Region.Framework.Scenes
1603 { 1611 {
1604 if (part != null) 1612 if (part != null)
1605 { 1613 {
1606 if (part.ParentGroup.Children.Count != 1) // Skip single 1614 if (part.ParentGroup.PrimCount != 1) // Skip single
1607 { 1615 {
1608 if (part.LinkNum < 2) // Root 1616 if (part.LinkNum < 2) // Root
1609 rootParts.Add(part); 1617 rootParts.Add(part);
@@ -1631,8 +1639,15 @@ namespace OpenSim.Region.Framework.Scenes
1631 // However, editing linked parts and unlinking may be different 1639 // However, editing linked parts and unlinking may be different
1632 // 1640 //
1633 SceneObjectGroup group = root.ParentGroup; 1641 SceneObjectGroup group = root.ParentGroup;
1634 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); 1642
1635 int numChildren = group.Children.Count; 1643 List<SceneObjectPart> newSet = null;
1644 int numChildren = -1;
1645
1646 lock (group.Children)
1647 {
1648 newSet = new List<SceneObjectPart>(group.Children.Values);
1649 numChildren = group.PrimCount;
1650 }
1636 1651
1637 // If there are prims left in a link set, but the root is 1652 // If there are prims left in a link set, but the root is
1638 // slated for unlink, we need to do this 1653 // slated for unlink, we need to do this
@@ -1711,12 +1726,17 @@ namespace OpenSim.Region.Framework.Scenes
1711 { 1726 {
1712 if (ent is SceneObjectGroup) 1727 if (ent is SceneObjectGroup)
1713 { 1728 {
1714 foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children) 1729 SceneObjectGroup sog = ent as SceneObjectGroup;
1730
1731 lock (sog.Children)
1715 { 1732 {
1716 if (subent.Value.LocalId == localID) 1733 foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
1717 { 1734 {
1718 objid = subent.Key; 1735 if (subent.Value.LocalId == localID)
1719 obj = subent.Value; 1736 {
1737 objid = subent.Key;
1738 obj = subent.Value;
1739 }
1720 } 1740 }
1721 } 1741 }
1722 } 1742 }
@@ -1781,7 +1801,8 @@ namespace OpenSim.Region.Framework.Scenes
1781 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 1801 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1782 if (original != null) 1802 if (original != null)
1783 { 1803 {
1784 if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition)) 1804 if (m_parentScene.Permissions.CanDuplicateObject(
1805 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1785 { 1806 {
1786 SceneObjectGroup copy = original.Copy(true); 1807 SceneObjectGroup copy = original.Copy(true);
1787 copy.AbsolutePosition = copy.AbsolutePosition + offset; 1808 copy.AbsolutePosition = copy.AbsolutePosition + offset;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 952d280..5ee8d73 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -213,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
213 /// </summary> 213 /// </summary>
214 public int PrimCount 214 public int PrimCount
215 { 215 {
216 get { return m_parts.Count; } 216 get { lock (m_parts) { return m_parts.Count; } }
217 } 217 }
218 218
219 protected Quaternion m_rotation = Quaternion.Identity; 219 protected Quaternion m_rotation = Quaternion.Identity;
@@ -237,6 +237,7 @@ namespace OpenSim.Region.Framework.Scenes
237 237
238 /// <value> 238 /// <value>
239 /// The parts of this scene object group. You must lock this property before using it. 239 /// The parts of this scene object group. You must lock this property before using it.
240 /// If you want to know the number of children, consider using the PrimCount property instead
240 /// </value> 241 /// </value>
241 public Dictionary<UUID, SceneObjectPart> Children 242 public Dictionary<UUID, SceneObjectPart> Children
242 { 243 {
@@ -298,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
298 { 299 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 300 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 301 }
302
301 if (RootPart.GetStatusSandbox()) 303 if (RootPart.GetStatusSandbox())
302 { 304 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 305 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -308,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
308 return; 310 return;
309 } 311 }
310 } 312 }
313
311 lock (m_parts) 314 lock (m_parts)
312 { 315 {
313 foreach (SceneObjectPart part in m_parts.Values) 316 foreach (SceneObjectPart part in m_parts.Values)
@@ -558,21 +561,23 @@ namespace OpenSim.Region.Framework.Scenes
558 if (m_rootPart.LocalId == 0) 561 if (m_rootPart.LocalId == 0)
559 m_rootPart.LocalId = m_scene.AllocateLocalId(); 562 m_rootPart.LocalId = m_scene.AllocateLocalId();
560 563
561 // No need to lock here since the object isn't yet in a scene 564 lock (m_parts)
562 foreach (SceneObjectPart part in m_parts.Values)
563 { 565 {
564 if (Object.ReferenceEquals(part, m_rootPart)) 566 foreach (SceneObjectPart part in m_parts.Values)
565 {
566 continue;
567 }
568
569 if (part.LocalId == 0)
570 { 567 {
571 part.LocalId = m_scene.AllocateLocalId(); 568 if (Object.ReferenceEquals(part, m_rootPart))
569 {
570 continue;
571 }
572
573 if (part.LocalId == 0)
574 {
575 part.LocalId = m_scene.AllocateLocalId();
576 }
577
578 part.ParentID = m_rootPart.LocalId;
579 //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);
572 } 580 }
573
574 part.ParentID = m_rootPart.LocalId;
575 //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);
576 } 581 }
577 582
578 ApplyPhysics(m_scene.m_physicalPrim); 583 ApplyPhysics(m_scene.m_physicalPrim);
@@ -670,7 +675,7 @@ namespace OpenSim.Region.Framework.Scenes
670 minY = 256f; 675 minY = 256f;
671 minZ = 8192f; 676 minZ = 8192f;
672 677
673 lock(m_parts); 678 lock(m_parts)
674 { 679 {
675 foreach (SceneObjectPart part in m_parts.Values) 680 foreach (SceneObjectPart part in m_parts.Values)
676 { 681 {
@@ -995,9 +1000,12 @@ namespace OpenSim.Region.Framework.Scenes
995 m_rootPart.AttachedAvatar = agentID; 1000 m_rootPart.AttachedAvatar = agentID;
996 1001
997 //Anakin Lohner bug #3839 1002 //Anakin Lohner bug #3839
998 foreach (SceneObjectPart p in m_parts.Values) 1003 lock (m_parts)
999 { 1004 {
1000 p.AttachedAvatar = agentID; 1005 foreach (SceneObjectPart p in m_parts.Values)
1006 {
1007 p.AttachedAvatar = agentID;
1008 }
1001 } 1009 }
1002 1010
1003 if (m_rootPart.PhysActor != null) 1011 if (m_rootPart.PhysActor != null)
@@ -1065,10 +1073,14 @@ namespace OpenSim.Region.Framework.Scenes
1065 1073
1066 AbsolutePosition = detachedpos; 1074 AbsolutePosition = detachedpos;
1067 m_rootPart.AttachedAvatar = UUID.Zero; 1075 m_rootPart.AttachedAvatar = UUID.Zero;
1068 //Anakin Lohner bug #3839 1076
1069 foreach (SceneObjectPart p in m_parts.Values) 1077 //Anakin Lohner bug #3839
1078 lock (m_parts)
1070 { 1079 {
1071 p.AttachedAvatar = UUID.Zero; 1080 foreach (SceneObjectPart p in m_parts.Values)
1081 {
1082 p.AttachedAvatar = UUID.Zero;
1083 }
1072 } 1084 }
1073 1085
1074 m_rootPart.SetParentLocalId(0); 1086 m_rootPart.SetParentLocalId(0);
@@ -1094,10 +1106,14 @@ namespace OpenSim.Region.Framework.Scenes
1094 } 1106 }
1095 1107
1096 m_rootPart.AttachedAvatar = UUID.Zero; 1108 m_rootPart.AttachedAvatar = UUID.Zero;
1109
1097 //Anakin Lohner bug #3839 1110 //Anakin Lohner bug #3839
1098 foreach (SceneObjectPart p in m_parts.Values) 1111 lock (m_parts)
1099 { 1112 {
1100 p.AttachedAvatar = UUID.Zero; 1113 foreach (SceneObjectPart p in m_parts.Values)
1114 {
1115 p.AttachedAvatar = UUID.Zero;
1116 }
1101 } 1117 }
1102 1118
1103 m_rootPart.SetParentLocalId(0); 1119 m_rootPart.SetParentLocalId(0);
@@ -1160,9 +1176,8 @@ namespace OpenSim.Region.Framework.Scenes
1160 part.ParentID = 0; 1176 part.ParentID = 0;
1161 part.LinkNum = 0; 1177 part.LinkNum = 0;
1162 1178
1163 // No locking required since the SOG should not be in the scene yet - one can't change root parts after 1179 lock (m_parts)
1164 // the scene object has been attached to the scene 1180 m_parts.Add(m_rootPart.UUID, m_rootPart);
1165 m_parts.Add(m_rootPart.UUID, m_rootPart);
1166 } 1181 }
1167 1182
1168 /// <summary> 1183 /// <summary>
@@ -1625,7 +1640,7 @@ namespace OpenSim.Region.Framework.Scenes
1625 } 1640 }
1626 1641
1627 /// <summary> 1642 /// <summary>
1628 /// 1643 /// Copy the given part as the root part of this scene object.
1629 /// </summary> 1644 /// </summary>
1630 /// <param name="part"></param> 1645 /// <param name="part"></param>
1631 /// <param name="cAgentID"></param> 1646 /// <param name="cAgentID"></param>
@@ -1882,11 +1897,12 @@ namespace OpenSim.Region.Framework.Scenes
1882 /// <param name="cGroupID"></param> 1897 /// <param name="cGroupID"></param>
1883 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1898 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1884 { 1899 {
1885 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1900 SceneObjectPart newPart = null;
1886 newPart.SetParent(this); 1901
1887
1888 lock (m_parts) 1902 lock (m_parts)
1889 { 1903 {
1904 newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1905 newPart.SetParent(this);
1890 m_parts.Add(newPart.UUID, newPart); 1906 m_parts.Add(newPart.UUID, newPart);
1891 } 1907 }
1892 1908
@@ -1903,14 +1919,15 @@ namespace OpenSim.Region.Framework.Scenes
1903 /// </summary> 1919 /// </summary>
1904 public void ResetIDs() 1920 public void ResetIDs()
1905 { 1921 {
1906 // As this is only ever called for prims which are not currently part of the scene (and hence 1922 lock (m_parts)
1907 // not accessible by clients), there should be no need to lock
1908 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
1909 m_parts.Clear();
1910 foreach (SceneObjectPart part in partsList)
1911 { 1923 {
1912 part.ResetIDs(part.LinkNum); // Don't change link nums 1924 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
1913 m_parts.Add(part.UUID, part); 1925 m_parts.Clear();
1926 foreach (SceneObjectPart part in partsList)
1927 {
1928 part.ResetIDs(part.LinkNum); // Don't change link nums
1929 m_parts.Add(part.UUID, part);
1930 }
1914 } 1931 }
1915 } 1932 }
1916 1933
@@ -2136,10 +2153,15 @@ namespace OpenSim.Region.Framework.Scenes
2136 public SceneObjectPart GetChildPart(UUID primID) 2153 public SceneObjectPart GetChildPart(UUID primID)
2137 { 2154 {
2138 SceneObjectPart childPart = null; 2155 SceneObjectPart childPart = null;
2139 if (m_parts.ContainsKey(primID)) 2156
2157 lock (m_parts)
2140 { 2158 {
2141 childPart = m_parts[primID]; 2159 if (m_parts.ContainsKey(primID))
2160 {
2161 childPart = m_parts[primID];
2162 }
2142 } 2163 }
2164
2143 return childPart; 2165 return childPart;
2144 } 2166 }
2145 2167
@@ -2174,9 +2196,10 @@ namespace OpenSim.Region.Framework.Scenes
2174 /// <returns></returns> 2196 /// <returns></returns>
2175 public bool HasChildPrim(UUID primID) 2197 public bool HasChildPrim(UUID primID)
2176 { 2198 {
2177 if (m_parts.ContainsKey(primID)) 2199 lock (m_parts)
2178 { 2200 {
2179 return true; 2201 if (m_parts.ContainsKey(primID))
2202 return true;
2180 } 2203 }
2181 2204
2182 return false; 2205 return false;
@@ -2370,17 +2393,19 @@ namespace OpenSim.Region.Framework.Scenes
2370 lock (m_parts) 2393 lock (m_parts)
2371 { 2394 {
2372 m_parts.Remove(linkPart.UUID); 2395 m_parts.Remove(linkPart.UUID);
2373 } 2396
2374 2397 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2375 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2376 RootPart.LinkNum = 0;
2377 else
2378 {
2379 foreach (SceneObjectPart p in m_parts.Values)
2380 { 2398 {
2381 if (p.LinkNum > linkPart.LinkNum) 2399 RootPart.LinkNum = 0;
2382 p.LinkNum--;
2383 } 2400 }
2401 else
2402 {
2403 foreach (SceneObjectPart p in m_parts.Values)
2404 {
2405 if (p.LinkNum > linkPart.LinkNum)
2406 p.LinkNum--;
2407 }
2408 }
2384 } 2409 }
2385 2410
2386 linkPart.ParentID = 0; 2411 linkPart.ParentID = 0;
@@ -2762,9 +2787,11 @@ namespace OpenSim.Region.Framework.Scenes
2762 public void UpdatePermissions(UUID AgentID, byte field, uint localID, 2787 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
2763 uint mask, byte addRemTF) 2788 uint mask, byte addRemTF)
2764 { 2789 {
2765 foreach (SceneObjectPart part in m_parts.Values) 2790 lock (m_parts)
2766 part.UpdatePermissions(AgentID, field, localID, mask, 2791 {
2767 addRemTF); 2792 foreach (SceneObjectPart part in m_parts.Values)
2793 part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2794 }
2768 2795
2769 HasGroupChanged = true; 2796 HasGroupChanged = true;
2770 } 2797 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 84b7365..e08fa77 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -601,7 +601,10 @@ namespace OpenSim.Region.Framework.Scenes
601 rootPart.Name = item.Name; 601 rootPart.Name = item.Name;
602 rootPart.Description = item.Description; 602 rootPart.Description = item.Description;
603 603
604 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); 604 List<SceneObjectPart> partList = null;
605
606 lock (group.Children)
607 partList = new List<SceneObjectPart>(group.Children.Values);
605 608
606 group.SetGroup(m_part.GroupID, null); 609 group.SetGroup(m_part.GroupID, null);
607 610
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
index 56656fc..de1e01c 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
@@ -121,16 +121,19 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
121 continue; 121 continue;
122 temp = (SceneObjectGroup) currObj; 122 temp = (SceneObjectGroup) currObj;
123 123
124 if (m_CMEntityHash.ContainsKey(temp.UUID)) 124 lock (temp.Children)
125 { 125 {
126 foreach (SceneObjectPart part in temp.Children.Values) 126 if (m_CMEntityHash.ContainsKey(temp.UUID))
127 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) 127 {
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)
128 missingList.Add(part); 135 missingList.Add(part);
129 } 136 }
130 else //Entire group is missing from revision. (and is a new part in region)
131 {
132 foreach (SceneObjectPart part in temp.Children.Values)
133 missingList.Add(part);
134 } 137 }
135 } 138 }
136 return missingList; 139 return missingList;
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
index 0dc78c0..e5fcb54 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -167,9 +167,12 @@ 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 foreach (SceneObjectPart part in group.Children.Values) 170 lock (group.Children)
171 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 171 {
172 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); 172 foreach (SceneObjectPart part in group.Children.Values)
173 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
174 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
175 }
173 } 176 }
174 177
175 /// <summary> 178 /// <summary>
@@ -207,8 +210,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
207 { 210 {
208 temp = SceneObjectSerializer.FromXml2Format(xml); 211 temp = SceneObjectSerializer.FromXml2Format(xml);
209 temp.SetScene(scene); 212 temp.SetScene(scene);
210 foreach (SceneObjectPart part in temp.Children.Values) 213
211 part.RegionHandle = scene.RegionInfo.RegionHandle; 214 lock (temp.Children)
215 {
216 foreach (SceneObjectPart part in temp.Children.Values)
217 part.RegionHandle = scene.RegionInfo.RegionHandle;
218 }
219
212 ReplacementList.Add(temp.UUID, (EntityBase)temp); 220 ReplacementList.Add(temp.UUID, (EntityBase)temp);
213 } 221 }
214 catch (Exception e) 222 catch (Exception e)
@@ -338,15 +346,20 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
338 System.Collections.ArrayList auraList = new System.Collections.ArrayList(); 346 System.Collections.ArrayList auraList = new System.Collections.ArrayList();
339 if (group == null) 347 if (group == null)
340 return null; 348 return null;
341 foreach (SceneObjectPart part in group.Children.Values) 349
350 lock (group.Children)
342 { 351 {
343 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 352 foreach (SceneObjectPart part in group.Children.Values)
344 { 353 {
345 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); 354 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
346 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); 355 {
347 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); 356 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale);
357 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
358 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
359 }
348 } 360 }
349 } 361 }
362
350 return auraList; 363 return auraList;
351 } 364 }
352 365
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
index 46fbd39..f75f40a 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
@@ -186,9 +186,12 @@ 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 foreach (SceneObjectPart part in group.Children.Values) 189 lock (group.Children)
190 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) 190 {
191 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); 191 foreach (SceneObjectPart part in group.Children.Values)
192 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
193 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
194 }
192 } 195 }
193 196
194 public void SendMetaEntitiesToNewClient(IClientAPI client) 197 public void SendMetaEntitiesToNewClient(IClientAPI client)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
index ada6701..2730eee 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -132,30 +132,33 @@ 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 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 135 lock (m_UnchangedEntity.Children)
136 { 136 {
137 // if scene list no longer contains this part, display translucent part and mark with red aura 137 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
138 if (!ContainsKey(sceneEntityList, part.UUID))
139 { 138 {
140 // if already displaying a red aura over part, make sure its red 139 // if scene list no longer contains this part, display translucent part and mark with red aura
141 if (m_AuraEntities.ContainsKey(part.UUID)) 140 if (!ContainsKey(sceneEntityList, part.UUID))
142 {
143 m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
144 }
145 else
146 { 141 {
147 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 142 // if already displaying a red aura over part, make sure its red
148 part.GetWorldPosition(), 143 if (m_AuraEntities.ContainsKey(part.UUID))
149 MetaEntity.TRANSLUCENT, 144 {
150 new Vector3(254,0,0), 145 m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
151 part.Scale 146 }
152 ); 147 else
153 m_AuraEntities.Add(part.UUID, auraGroup); 148 {
149 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
150 part.GetWorldPosition(),
151 MetaEntity.TRANSLUCENT,
152 new Vector3(254,0,0),
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);
154 } 159 }
155 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); 160 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
156 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
157 } 161 }
158 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
159 } 162 }
160 163
161 // a deleted part has no where to point a beam particle system, 164 // a deleted part has no where to point a beam particle system,
@@ -180,8 +183,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
180 /// </summary> 183 /// </summary>
181 public bool HasChildPrim(UUID uuid) 184 public bool HasChildPrim(UUID uuid)
182 { 185 {
183 if (m_UnchangedEntity.Children.ContainsKey(uuid)) 186 lock (m_UnchangedEntity.Children)
184 return true; 187 if (m_UnchangedEntity.Children.ContainsKey(uuid))
188 return true;
189
185 return false; 190 return false;
186 } 191 }
187 192
@@ -190,9 +195,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
190 /// </summary> 195 /// </summary>
191 public bool HasChildPrim(uint localID) 196 public bool HasChildPrim(uint localID)
192 { 197 {
193 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 198 lock (m_UnchangedEntity.Children)
194 if (part.LocalId == localID) 199 {
195 return true; 200 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
201 if (part.LocalId == localID)
202 return true;
203 }
204
196 return false; 205 return false;
197 } 206 }
198 207
@@ -228,37 +237,72 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
228 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user 237 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
229 // had originally saved. 238 // had originally saved.
230 // m_Entity will NOT necessarily be the same entity as the user had saved. 239 // m_Entity will NOT necessarily be the same entity as the user had saved.
231 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) 240 lock (m_UnchangedEntity.Children)
232 { 241 {
233 //This is the part that we use to show changes. 242 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
234 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
235 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
236 { 243 {
237 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; 244 //This is the part that we use to show changes.
238 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); 245 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
239 if (differences != Diff.NONE) 246 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
240 metaEntityPart.Text = "CHANGE: " + differences.ToString();
241 if (differences != 0)
242 { 247 {
243 // Root Part that has been modified 248 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
244 if ((differences&Diff.POSITION) > 0) 249 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
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
245 { 290 {
246 // If the position of any part has changed, make sure the RootPart of the
247 // meta entity is pointing with a beam particle system
248 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) 291 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
249 { 292 {
250 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); 293 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
251 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); 294 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
252 } 295 }
253 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, 296 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
254 m_UnchangedEntity.RootPart.GetWorldPosition(), 297 {
255 MetaEntity.TRANSLUCENT, 298 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
256 sceneEntityPart, 299 m_AuraEntities.Remove(UnchangedPart.UUID);
257 new Vector3(0,0,254) 300 }
258 ); 301 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
259 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
260 } 302 }
261 303 }
304 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
305 {
262 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) 306 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
263 { 307 {
264 m_AuraEntities[UnchangedPart.UUID].HideFromAll(); 308 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
@@ -267,48 +311,17 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
267 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 311 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
268 UnchangedPart.GetWorldPosition(), 312 UnchangedPart.GetWorldPosition(),
269 MetaEntity.TRANSLUCENT, 313 MetaEntity.TRANSLUCENT,
270 new Vector3(0,0,254), 314 new Vector3(254,0,0),
271 UnchangedPart.Scale 315 UnchangedPart.Scale
272 ); 316 );
273 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); 317 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
274 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); 318 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
275 319
276 DiffersFromSceneGroup = true; 320 DiffersFromSceneGroup = true;
277 } 321 }
278 else // no differences between scene part and meta part
279 {
280 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
281 {
282 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
283 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
284 }
285 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
286 {
287 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
288 m_AuraEntities.Remove(UnchangedPart.UUID);
289 }
290 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
291 }
292 }
293 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
294 {
295 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
296 {
297 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
298 m_AuraEntities.Remove(UnchangedPart.UUID);
299 }
300 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
301 UnchangedPart.GetWorldPosition(),
302 MetaEntity.TRANSLUCENT,
303 new Vector3(254,0,0),
304 UnchangedPart.Scale
305 );
306 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
307 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
308
309 DiffersFromSceneGroup = true;
310 } 322 }
311 } 323 }
324
312 return changed; 325 return changed;
313 } 326 }
314 327
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index 841ee00..796f437 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -150,15 +150,19 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
150 { 150 {
151 //make new uuids 151 //make new uuids
152 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>(); 152 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>();
153 foreach (SceneObjectPart part in m_Entity.Children.Values) 153
154 lock (m_Entity.Children)
154 { 155 {
155 part.ResetIDs(part.LinkNum); 156 foreach (SceneObjectPart part in m_Entity.Children.Values)
156 parts.Add(part.UUID, part); 157 {
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;
157 } 165 }
158
159 //finalize
160 m_Entity.RootPart.PhysActor = null;
161 m_Entity.Children = parts;
162 } 166 }
163 167
164 #endregion Protected Methods 168 #endregion Protected Methods
@@ -173,8 +177,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
173 //This deletes the group without removing from any databases. 177 //This deletes the group without removing from any databases.
174 //This is important because we are not IN any database. 178 //This is important because we are not IN any database.
175 //m_Entity.FakeDeleteGroup(); 179 //m_Entity.FakeDeleteGroup();
176 foreach (SceneObjectPart part in m_Entity.Children.Values) 180 lock (m_Entity.Children)
177 client.SendKillObject(m_Entity.RegionHandle, part.LocalId); 181 {
182 foreach (SceneObjectPart part in m_Entity.Children.Values)
183 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
184 }
178 } 185 }
179 186
180 /// <summary> 187 /// <summary>
@@ -182,12 +189,15 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
182 /// </summary> 189 /// </summary>
183 public virtual void HideFromAll() 190 public virtual void HideFromAll()
184 { 191 {
185 foreach (SceneObjectPart part in m_Entity.Children.Values) 192 lock (m_Entity.Children)
186 { 193 {
187 m_Entity.Scene.ForEachClient( 194 foreach (SceneObjectPart part in m_Entity.Children.Values)
188 delegate(IClientAPI controller) 195 {
189 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } 196 m_Entity.Scene.ForEachClient(
190 ); 197 delegate(IClientAPI controller)
198 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
199 );
200 }
191 } 201 }
192 } 202 }
193 203
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 96cccb7..34171b0 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -185,14 +185,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
185 get 185 get
186 { 186 {
187 SceneObjectPart my = GetSOP(); 187 SceneObjectPart my = GetSOP();
188 int total = my.ParentGroup.Children.Count; 188 IObject[] rets = null;
189 189
190 IObject[] rets = new IObject[total]; 190 lock (my.ParentGroup.Children)
191
192 int i = 0;
193 foreach (KeyValuePair<UUID, SceneObjectPart> pair in my.ParentGroup.Children)
194 { 191 {
195 rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security); 192 int total = my.ParentGroup.Children.Count;
193
194 rets = new IObject[total];
195
196 int i = 0;
197 foreach (KeyValuePair<UUID, SceneObjectPart> pair in my.ParentGroup.Children)
198 {
199 rets[i++] = new SOPObject(m_rootScene, pair.Value.LocalId, m_security);
200 }
196 } 201 }
197 202
198 return rets; 203 return rets;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 21604d0..af42dae 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -235,7 +235,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
235 { 235 {
236 case ScriptBaseClass.LINK_SET: 236 case ScriptBaseClass.LINK_SET:
237 if (m_host.ParentGroup != null) 237 if (m_host.ParentGroup != null)
238 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); 238 {
239 lock (m_host.ParentGroup.Children)
240 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
241 }
239 return ret; 242 return ret;
240 243
241 case ScriptBaseClass.LINK_ROOT: 244 case ScriptBaseClass.LINK_ROOT:
@@ -250,7 +253,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
250 case ScriptBaseClass.LINK_ALL_OTHERS: 253 case ScriptBaseClass.LINK_ALL_OTHERS:
251 if (m_host.ParentGroup == null) 254 if (m_host.ParentGroup == null)
252 return new List<SceneObjectPart>(); 255 return new List<SceneObjectPart>();
253 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); 256
257 lock (m_host.ParentGroup.Children)
258 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
259
254 if (ret.Contains(m_host)) 260 if (ret.Contains(m_host))
255 ret.Remove(m_host); 261 ret.Remove(m_host);
256 return ret; 262 return ret;
@@ -258,7 +264,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
258 case ScriptBaseClass.LINK_ALL_CHILDREN: 264 case ScriptBaseClass.LINK_ALL_CHILDREN:
259 if (m_host.ParentGroup == null) 265 if (m_host.ParentGroup == null)
260 return new List<SceneObjectPart>(); 266 return new List<SceneObjectPart>();
261 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); 267
268 lock (m_host.ParentGroup.Children)
269 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
270
262 if (ret.Contains(m_host.ParentGroup.RootPart)) 271 if (ret.Contains(m_host.ParentGroup.RootPart))
263 ret.Remove(m_host.ParentGroup.RootPart); 272 ret.Remove(m_host.ParentGroup.RootPart);
264 return ret; 273 return ret;
@@ -1178,12 +1187,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1178 if (group == null) 1187 if (group == null)
1179 return; 1188 return;
1180 bool allow = true; 1189 bool allow = true;
1181 foreach (SceneObjectPart part in group.Children.Values) 1190
1191 lock (group.Children)
1182 { 1192 {
1183 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1193 foreach (SceneObjectPart part in group.Children.Values)
1184 { 1194 {
1185 allow = false; 1195 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1186 break; 1196 {
1197 allow = false;
1198 break;
1199 }
1187 } 1200 }
1188 } 1201 }
1189 1202
@@ -3492,7 +3505,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3492 { 3505 {
3493 m_host.AddScriptLPS(1); 3506 m_host.AddScriptLPS(1);
3494 3507
3495 if (m_host.ParentGroup.Children.Count > 1) 3508 if (m_host.ParentGroup.PrimCount > 1)
3496 { 3509 {
3497 return m_host.LinkNum; 3510 return m_host.LinkNum;
3498 } 3511 }
@@ -3604,15 +3617,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3604 case ScriptBaseClass.LINK_ALL_OTHERS: 3617 case ScriptBaseClass.LINK_ALL_OTHERS:
3605 case ScriptBaseClass.LINK_ALL_CHILDREN: 3618 case ScriptBaseClass.LINK_ALL_CHILDREN:
3606 case ScriptBaseClass.LINK_THIS: 3619 case ScriptBaseClass.LINK_THIS:
3607 foreach (SceneObjectPart part in parentPrim.Children.Values) 3620 lock (parentPrim.Children)
3608 { 3621 {
3609 if (part.UUID != m_host.UUID) 3622 foreach (SceneObjectPart part in parentPrim.Children.Values)
3610 { 3623 {
3611 childPrim = part; 3624 if (part.UUID != m_host.UUID)
3612 break; 3625 {
3626 childPrim = part;
3627 break;
3628 }
3613 } 3629 }
3630 break;
3614 } 3631 }
3615 break;
3616 default: 3632 default:
3617 childPrim = parentPrim.GetLinkNumPart(linknum); 3633 childPrim = parentPrim.GetLinkNumPart(linknum);
3618 if (childPrim.UUID == m_host.UUID) 3634 if (childPrim.UUID == m_host.UUID)
@@ -3623,27 +3639,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3623 if (linknum == ScriptBaseClass.LINK_ROOT) 3639 if (linknum == ScriptBaseClass.LINK_ROOT)
3624 { 3640 {
3625 // Restructuring Multiple Prims. 3641 // Restructuring Multiple Prims.
3626 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3642 lock (parentPrim.Children)
3627 parts.Remove(parentPrim.RootPart);
3628 foreach (SceneObjectPart part in parts)
3629 {
3630 parentPrim.DelinkFromGroup(part.LocalId, true);
3631 }
3632 parentPrim.HasGroupChanged = true;
3633 parentPrim.ScheduleGroupForFullUpdate();
3634 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3635
3636 if (parts.Count > 0)
3637 { 3643 {
3638 SceneObjectPart newRoot = parts[0]; 3644 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
3639 parts.Remove(newRoot); 3645 parts.Remove(parentPrim.RootPart);
3640 foreach (SceneObjectPart part in parts) 3646 foreach (SceneObjectPart part in parts)
3641 { 3647 {
3642 part.UpdateFlag = 0; 3648 parentPrim.DelinkFromGroup(part.LocalId, true);
3643 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3649 }
3650 parentPrim.HasGroupChanged = true;
3651 parentPrim.ScheduleGroupForFullUpdate();
3652 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3653
3654 if (parts.Count > 0)
3655 {
3656 SceneObjectPart newRoot = parts[0];
3657 parts.Remove(newRoot);
3658 foreach (SceneObjectPart part in parts)
3659 {
3660 part.UpdateFlag = 0;
3661 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3662 }
3663 newRoot.ParentGroup.HasGroupChanged = true;
3664 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3644 } 3665 }
3645 newRoot.ParentGroup.HasGroupChanged = true;
3646 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3647 } 3666 }
3648 } 3667 }
3649 else 3668 else
@@ -3665,16 +3684,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3665 if (parentPrim.RootPart.AttachmentPoint != 0) 3684 if (parentPrim.RootPart.AttachmentPoint != 0)
3666 return; // Fail silently if attached 3685 return; // Fail silently if attached
3667 3686
3668 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3687 lock (parentPrim.Children)
3669 parts.Remove(parentPrim.RootPart);
3670
3671 foreach (SceneObjectPart part in parts)
3672 { 3688 {
3673 parentPrim.DelinkFromGroup(part.LocalId, true); 3689 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
3674 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3690 parts.Remove(parentPrim.RootPart);
3691
3692 foreach (SceneObjectPart part in parts)
3693 {
3694 parentPrim.DelinkFromGroup(part.LocalId, true);
3695 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3696 }
3697 parentPrim.HasGroupChanged = true;
3698 parentPrim.ScheduleGroupForFullUpdate();
3675 } 3699 }
3676 parentPrim.HasGroupChanged = true;
3677 parentPrim.ScheduleGroupForFullUpdate();
3678 } 3700 }
3679 3701
3680 public LSL_String llGetLinkKey(int linknum) 3702 public LSL_String llGetLinkKey(int linknum)
@@ -4200,7 +4222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4200 { 4222 {
4201 partItemID = item.ItemID; 4223 partItemID = item.ItemID;
4202 int linkNumber = m_host.LinkNum; 4224 int linkNumber = m_host.LinkNum;
4203 if (m_host.ParentGroup.Children.Count == 1) 4225 if (m_host.ParentGroup.PrimCount == 1)
4204 linkNumber = 0; 4226 linkNumber = 0;
4205 4227
4206 object[] resobj = new object[] 4228 object[] resobj = new object[]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 4855d64..41501f2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -209,12 +209,15 @@ namespace OpenSim.Region.ScriptEngine.Shared
209 else 209 else
210 Type = 0x02; // Passive 210 Type = 0x02; // Passive
211 211
212 foreach (SceneObjectPart p in part.ParentGroup.Children.Values) 212 lock (part.ParentGroup.Children)
213 { 213 {
214 if (p.Inventory.ContainsScripts()) 214 foreach (SceneObjectPart p in part.ParentGroup.Children.Values)
215 { 215 {
216 Type |= 0x08; // Scripted 216 if (p.Inventory.ContainsScripts())
217 break; 217 {
218 Type |= 0x08; // Scripted
219 break;
220 }
218 } 221 }
219 } 222 }
220 223