aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2010-10-07 01:13:17 +0200
committerMelanie2011-04-03 20:24:44 +0100
commitb385d4aa036ad7bf58d033a9923452535c82ef69 (patch)
treefd6511be9df96c1504dbfa3e1308d5e708542daf /OpenSim/Region
parentMake CHANGED_OWNER work for deeding and god-mode in-world change (diff)
downloadopensim-SC_OLD-b385d4aa036ad7bf58d033a9923452535c82ef69.zip
opensim-SC_OLD-b385d4aa036ad7bf58d033a9923452535c82ef69.tar.gz
opensim-SC_OLD-b385d4aa036ad7bf58d033a9923452535c82ef69.tar.bz2
opensim-SC_OLD-b385d4aa036ad7bf58d033a9923452535c82ef69.tar.xz
Implement taking of coalesced objects.
WARNING!!!!! You can TAKE them, but you can't REZ them again. Only the first of the contained objects will rez, the rest is inaccessible until rezzing them is implemented. Also, rotations are not explicitly stored. This MAY work. Or not.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs459
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs9
3 files changed, 274 insertions, 198 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 8d0c35a..88dff02 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Xml;
31using System.Reflection; 32using System.Reflection;
32using System.Threading; 33using System.Threading;
33 34
@@ -205,11 +206,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
205 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, 206 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
206 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 207 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient)
207 { 208 {
208 // HACK: This is only working for lists containing a single item!
209 // It's just a hack to make this WIP compile and run. Nothing
210 // currently calls this with multiple items.
211 UUID ret = UUID.Zero; 209 UUID ret = UUID.Zero;
212 210
211 // The following code groups the SOG's by owner. No objects
212 // belonging to different people can be coalesced, for obvious
213 // reasons.
213 Dictionary<UUID, List<SceneObjectGroup>> deletes = 214 Dictionary<UUID, List<SceneObjectGroup>> deletes =
214 new Dictionary<UUID, List<SceneObjectGroup>>(); 215 new Dictionary<UUID, List<SceneObjectGroup>>();
215 216
@@ -221,262 +222,328 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
221 deletes[g.OwnerID].Add(g); 222 deletes[g.OwnerID].Add(g);
222 } 223 }
223 224
225 // This is pethod scoped and will be returned. It will be the
226 // last created asset id
227 UUID assetID = UUID.Zero;
228
229 // Each iteration is really a separate asset being created,
230 // with distinct destinations as well.
224 foreach (List<SceneObjectGroup> objlist in deletes.Values) 231 foreach (List<SceneObjectGroup> objlist in deletes.Values)
225 { 232 {
226 foreach (SceneObjectGroup g in objlist) 233 Dictionary<UUID, string> xmlStrings =
227 ret = DeleteToInventory(action, folderID, g, remoteClient); 234 new Dictionary<UUID, string>();
228 }
229
230 return ret;
231 }
232 235
233 private UUID DeleteToInventory(DeRezAction action, UUID folderID, 236 foreach (SceneObjectGroup objectGroup in objlist)
234 SceneObjectGroup objectGroup, IClientAPI remoteClient) 237 {
235 { 238 Vector3 inventoryStoredPosition = new Vector3
236 UUID assetID = UUID.Zero; 239 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
240 ? 250
241 : objectGroup.AbsolutePosition.X)
242 ,
243 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
244 ? 250
245 : objectGroup.AbsolutePosition.X,
246 objectGroup.AbsolutePosition.Z);
237 247
238 Vector3 inventoryStoredPosition = new Vector3 248 Vector3 originalPosition = objectGroup.AbsolutePosition;
239 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
240 ? 250
241 : objectGroup.AbsolutePosition.X)
242 ,
243 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
244 ? 250
245 : objectGroup.AbsolutePosition.X,
246 objectGroup.AbsolutePosition.Z);
247 249
248 Vector3 originalPosition = objectGroup.AbsolutePosition; 250 // Restore attachment data after trip through the sim
251 if (objectGroup.RootPart.AttachPoint > 0)
252 inventoryStoredPosition = objectGroup.RootPart.AttachOffset;
253 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
249 254
250 objectGroup.AbsolutePosition = inventoryStoredPosition; 255 objectGroup.AbsolutePosition = inventoryStoredPosition;
251 256
252 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); 257 // Make sure all bits but the ones we want are clear
258 // on take.
259 // This will be applied to the current perms, so
260 // it will do what we want.
261 objectGroup.RootPart.NextOwnerMask &=
262 ((uint)PermissionMask.Copy |
263 (uint)PermissionMask.Transfer |
264 (uint)PermissionMask.Modify);
265 objectGroup.RootPart.NextOwnerMask |=
266 (uint)PermissionMask.Move;
253 267
254 objectGroup.AbsolutePosition = originalPosition; 268 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
255 269
256 // Get the user info of the item destination 270 objectGroup.AbsolutePosition = originalPosition;
257 //
258 UUID userID = UUID.Zero;
259 271
260 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || 272 xmlStrings[objectGroup.UUID] = sceneObjectXml;
261 action == DeRezAction.SaveToExistingUserInventoryItem) 273 }
262 {
263 // Take or take copy require a taker
264 // Saving changes requires a local user
265 //
266 if (remoteClient == null)
267 return UUID.Zero;
268 274
269 userID = remoteClient.AgentId; 275 string itemXml;
270 }
271 else
272 {
273 // All returns / deletes go to the object owner
274 //
275 276
276 userID = objectGroup.RootPart.OwnerID; 277 if (objlist.Count > 1)
277 } 278 {
279 float minX, minY, minZ;
280 float maxX, maxY, maxZ;
278 281
279 if (userID == UUID.Zero) // Can't proceed 282 Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist,
280 { 283 out minX, out maxX, out minY, out maxY,
281 return UUID.Zero; 284 out minZ, out maxZ);
282 }
283 285
284 // If we're returning someone's item, it goes back to the 286 // CreateWrapper
285 // owner's Lost And Found folder. 287 XmlDocument itemDoc = new XmlDocument();
286 // Delete is treated like return in this case 288 XmlElement root = itemDoc.CreateElement("", "CoalescedObject", "");
287 // Deleting your own items makes them go to trash 289 itemDoc.AppendChild(root);
288 //
289 290
290 InventoryFolderBase folder = null; 291 // Embed the offsets into the group XML
291 InventoryItemBase item = null; 292 for ( int i = 0 ; i < objlist.Count ; i++ )
293 {
294 XmlDocument doc = new XmlDocument();
295 SceneObjectGroup g = objlist[i];
296 doc.LoadXml(xmlStrings[g.UUID]);
297 XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup");
298 e.SetAttribute("offsetx", offsets[i].X.ToString());
299 e.SetAttribute("offsety", offsets[i].Y.ToString());
300 e.SetAttribute("offsetz", offsets[i].Z.ToString());
301
302 XmlNode objectNode = itemDoc.ImportNode(e, true);
303 root.AppendChild(objectNode);
304 }
292 305
293 if (DeRezAction.SaveToExistingUserInventoryItem == action) 306 float sizeX = maxX - minX;
294 { 307 float sizeY = maxY - minY;
295 item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID); 308 float sizeZ = maxZ - minZ;
296 item = m_Scene.InventoryService.GetItem(item);
297 309
298 //item = userInfo.RootFolder.FindItem( 310 root.SetAttribute("x", sizeX.ToString());
299 // objectGroup.RootPart.FromUserInventoryItemID); 311 root.SetAttribute("y", sizeY.ToString());
312 root.SetAttribute("z", sizeZ.ToString());
300 313
301 if (null == item) 314 itemXml = itemDoc.InnerXml;
315 }
316 else
302 { 317 {
303 m_log.DebugFormat( 318 itemXml = xmlStrings[objlist[0].UUID];
304 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
305 objectGroup.Name, objectGroup.UUID);
306 return UUID.Zero;
307 } 319 }
308 } 320
309 else 321 // Get the user info of the item destination
310 {
311 // Folder magic
312 // 322 //
313 if (action == DeRezAction.Delete) 323 UUID userID = UUID.Zero;
324
325 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
326 action == DeRezAction.SaveToExistingUserInventoryItem)
314 { 327 {
315 // Deleting someone else's item 328 // Take or take copy require a taker
329 // Saving changes requires a local user
316 // 330 //
317 if (remoteClient == null || 331 if (remoteClient == null)
318 objectGroup.OwnerID != remoteClient.AgentId) 332 return UUID.Zero;
319 {
320 333
321 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 334 userID = remoteClient.AgentId;
322 }
323 else
324 {
325 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
326 }
327 } 335 }
328 else if (action == DeRezAction.Return) 336 else
329 { 337 {
330 338 // All returns / deletes go to the object owner
331 // Dump to lost + found unconditionally
332 // 339 //
333 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 340
341 userID = objlist[0].RootPart.OwnerID;
334 } 342 }
335 343
336 if (folderID == UUID.Zero && folder == null) 344 if (userID == UUID.Zero) // Can't proceed
337 { 345 {
338 if (action == DeRezAction.Delete) 346 return UUID.Zero;
347 }
348
349 // If we're returning someone's item, it goes back to the
350 // owner's Lost And Found folder.
351 // Delete is treated like return in this case
352 // Deleting your own items makes them go to trash
353 //
354
355 InventoryFolderBase folder = null;
356 InventoryItemBase item = null;
357
358 if (DeRezAction.SaveToExistingUserInventoryItem == action)
359 {
360 item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID);
361 item = m_Scene.InventoryService.GetItem(item);
362
363 //item = userInfo.RootFolder.FindItem(
364 // objectGroup.RootPart.FromUserInventoryItemID);
365
366 if (null == item)
339 { 367 {
340 // Deletes go to trash by default 368 m_log.DebugFormat(
341 // 369 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
342 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); 370 objlist[0].Name, objlist[0].UUID);
371 return UUID.Zero;
343 } 372 }
344 else 373 }
374 else
375 {
376 // Folder magic
377 //
378 if (action == DeRezAction.Delete)
345 { 379 {
380 // Deleting someone else's item
381 //
346 if (remoteClient == null || 382 if (remoteClient == null ||
347 objectGroup.OwnerID != remoteClient.AgentId) 383 objlist[0].OwnerID != remoteClient.AgentId)
348 { 384 {
349 // Taking copy of another person's item. Take to 385
350 // Objects folder. 386 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
351 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
352 } 387 }
353 else 388 else
354 { 389 {
355 // Catch all. Use lost & found 390 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
391 }
392 }
393 else if (action == DeRezAction.Return)
394 {
395
396 // Dump to lost + found unconditionally
397 //
398 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
399 }
400
401 if (folderID == UUID.Zero && folder == null)
402 {
403 if (action == DeRezAction.Delete)
404 {
405 // Deletes go to trash by default
356 // 406 //
407 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
408 }
409 else
410 {
411 if (remoteClient == null ||
412 objlist[0].OwnerID != remoteClient.AgentId)
413 {
414 // Taking copy of another person's item. Take to
415 // Objects folder.
416 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
417 }
418 else
419 {
420 // Catch all. Use lost & found
421 //
357 422
358 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 423 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
424 }
359 } 425 }
360 } 426 }
361 }
362 427
363 // Override and put into where it came from, if it came 428 // Override and put into where it came from, if it came
364 // from anywhere in inventory 429 // from anywhere in inventory
365 // 430 //
366 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) 431 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
367 {
368 if (objectGroup.RootPart.FromFolderID != UUID.Zero)
369 { 432 {
370 InventoryFolderBase f = new InventoryFolderBase(objectGroup.RootPart.FromFolderID, userID); 433 if (objlist[0].RootPart.FromFolderID != UUID.Zero)
371 folder = m_Scene.InventoryService.GetFolder(f); 434 {
435 InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID);
436 folder = m_Scene.InventoryService.GetFolder(f);
437 }
372 } 438 }
373 }
374
375 if (folder == null) // None of the above
376 {
377 folder = new InventoryFolderBase(folderID);
378 439
379 if (folder == null) // Nowhere to put it 440 if (folder == null) // None of the above
380 { 441 {
381 return UUID.Zero; 442 folder = new InventoryFolderBase(folderID);
382 }
383 }
384 443
385 item = new InventoryItemBase(); 444 if (folder == null) // Nowhere to put it
386 item.CreatorId = objectGroup.RootPart.CreatorID.ToString(); 445 {
387 item.CreatorData = objectGroup.RootPart.CreatorData; 446 return UUID.Zero;
388 item.ID = UUID.Random(); 447 }
389 item.InvType = (int)InventoryType.Object; 448 }
390 item.Folder = folder.ID;
391 item.Owner = userID;
392 }
393 449
394 AssetBase asset = CreateAsset( 450 item = new InventoryItemBase();
395 objectGroup.GetPartName(objectGroup.RootPart.LocalId), 451 // Can't know creator is the same, so null it in inventory
396 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), 452 if (objlist.Count > 1)
397 (sbyte)AssetType.Object, 453 item.CreatorId = UUID.Zero.ToString();
398 Utils.StringToBytes(sceneObjectXml), 454 else
399 objectGroup.OwnerID.ToString()); 455 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
400 m_Scene.AssetService.Store(asset); 456 item.ID = UUID.Random();
401 assetID = asset.FullID; 457 item.InvType = (int)InventoryType.Object;
458 item.Folder = folder.ID;
459 item.Owner = userID;
460 if (objlist.Count > 1)
461 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
462 }
402 463
403 if (DeRezAction.SaveToExistingUserInventoryItem == action) 464 AssetBase asset = CreateAsset(
404 { 465 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
405 item.AssetID = asset.FullID; 466 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
406 m_Scene.InventoryService.UpdateItem(item); 467 (sbyte)AssetType.Object,
407 } 468 Utils.StringToBytes(itemXml),
408 else 469 objlist[0].OwnerID.ToString());
409 { 470 m_Scene.AssetService.Store(asset);
410 item.AssetID = asset.FullID; 471 assetID = asset.FullID;
411 472
412 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 473 if (DeRezAction.SaveToExistingUserInventoryItem == action)
413 { 474 {
414 uint perms = objectGroup.GetEffectivePermissions(); 475 item.AssetID = asset.FullID;
415 uint nextPerms = (perms & 7) << 13; 476 m_Scene.InventoryService.UpdateItem(item);
416 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
417 perms &= ~(uint)PermissionMask.Copy;
418 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
419 perms &= ~(uint)PermissionMask.Transfer;
420 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
421 perms &= ~(uint)PermissionMask.Modify;
422
423 // Make sure all bits but the ones we want are clear
424 // on take.
425 // This will be applied to the current perms, so
426 // it will do what we want.
427 objectGroup.RootPart.NextOwnerMask &=
428 ((uint)PermissionMask.Copy |
429 (uint)PermissionMask.Transfer |
430 (uint)PermissionMask.Modify);
431 objectGroup.RootPart.NextOwnerMask |=
432 (uint)PermissionMask.Move;
433
434 item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask;
435 item.CurrentPermissions = item.BasePermissions;
436 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
437 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask;
438 item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask;
439
440 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
441 } 477 }
442 else 478 else
443 { 479 {
444 item.BasePermissions = objectGroup.GetEffectivePermissions(); 480 item.AssetID = asset.FullID;
445 item.CurrentPermissions = objectGroup.GetEffectivePermissions();
446 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
447 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask;
448 item.GroupPermissions = objectGroup.RootPart.GroupMask;
449 481
450 item.CurrentPermissions &= 482 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
451 ((uint)PermissionMask.Copy | 483 foreach (SceneObjectGroup grp in objlist)
452 (uint)PermissionMask.Transfer | 484 effectivePerms &= grp.GetEffectivePermissions();
453 (uint)PermissionMask.Modify | 485 effectivePerms |= (uint)PermissionMask.Move;
454 (uint)PermissionMask.Move |
455 7); // Preserve folded permissions
456 }
457 486
458 // TODO: add the new fields (Flags, Sale info, etc) 487 if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
459 item.CreationDate = Util.UnixTimeSinceEpoch(); 488 {
460 item.Description = asset.Description; 489 uint perms = effectivePerms;
461 item.Name = asset.Name; 490 uint nextPerms = (perms & 7) << 13;
462 item.AssetType = asset.Type; 491 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
492 perms &= ~(uint)PermissionMask.Copy;
493 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
494 perms &= ~(uint)PermissionMask.Transfer;
495 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
496 perms &= ~(uint)PermissionMask.Modify;
497
498 item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask;
499 item.CurrentPermissions = item.BasePermissions;
500 item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask;
501 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask;
502 item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask;
503
504 // Magic number badness. Maybe this deserves an enum.
505 // bit 4 (16) is the "Slam" bit, it means treat as passed
506 // and apply next owner perms on rez
507 item.CurrentPermissions |= 16; // Slam!
508 }
509 else
510 {
511 item.BasePermissions = effectivePerms;
512 item.CurrentPermissions = effectivePerms;
513 item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms;
514 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms;
515 item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms;
516
517 item.CurrentPermissions &=
518 ((uint)PermissionMask.Copy |
519 (uint)PermissionMask.Transfer |
520 (uint)PermissionMask.Modify |
521 (uint)PermissionMask.Move |
522 7); // Preserve folded permissions
523 }
463 524
464 m_Scene.AddInventoryItem(item); 525 // TODO: add the new fields (Flags, Sale info, etc)
526 item.CreationDate = Util.UnixTimeSinceEpoch();
527 item.Description = asset.Description;
528 item.Name = asset.Name;
529 item.AssetType = asset.Type;
465 530
466 if (remoteClient != null && item.Owner == remoteClient.AgentId) 531 m_Scene.AddInventoryItem(item);
467 { 532
468 remoteClient.SendInventoryItemCreateUpdate(item, 0); 533 if (remoteClient != null && item.Owner == remoteClient.AgentId)
469 }
470 else
471 {
472 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
473 if (notifyUser != null)
474 { 534 {
475 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); 535 remoteClient.SendInventoryItemCreateUpdate(item, 0);
536 }
537 else
538 {
539 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
540 if (notifyUser != null)
541 {
542 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
543 }
476 } 544 }
477 } 545 }
478 } 546 }
479
480 return assetID; 547 return assetID;
481 } 548 }
482 549
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 64567db..8feb022 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
137 x = m_inventoryDeletes.Dequeue(); 137 x = m_inventoryDeletes.Dequeue();
138 138
139 m_log.DebugFormat( 139 m_log.DebugFormat(
140 "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left); 140 "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count);
141 141
142 try 142 try
143 { 143 {
@@ -177,4 +177,4 @@ namespace OpenSim.Region.Framework.Scenes
177 return false; 177 return false;
178 } 178 }
179 } 179 }
180} \ No newline at end of file 180}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 353b7c2..35a798e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4865,8 +4865,17 @@ namespace OpenSim.Region.Framework.Scenes
4865 { 4865 {
4866 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; 4866 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ;
4867 4867
4868 Vector3 vec = g.AbsolutePosition;
4869
4868 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 4870 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4869 4871
4872 ominX += vec.X;
4873 omaxX += vec.X;
4874 ominY += vec.Y;
4875 omaxY += vec.Y;
4876 ominZ += vec.Z;
4877 omaxZ += vec.Z;
4878
4870 if (minX > ominX) 4879 if (minX > ominX)
4871 minX = ominX; 4880 minX = ominX;
4872 if (minY > ominY) 4881 if (minY > ominY)