aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs754
1 files changed, 429 insertions, 325 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 798547a..73b0a35 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,329 @@ 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 235
230 return ret; 236 foreach (SceneObjectGroup objectGroup in objlist)
231 } 237 {
238 Vector3 inventoryStoredPosition = new Vector3
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);
232 247
233 private UUID DeleteToInventory(DeRezAction action, UUID folderID, 248 Vector3 originalPosition = objectGroup.AbsolutePosition;
234 SceneObjectGroup objectGroup, IClientAPI remoteClient)
235 {
236 UUID assetID = UUID.Zero;
237 249
238 Vector3 inventoryStoredPosition = new Vector3 250 objectGroup.AbsolutePosition = inventoryStoredPosition;
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 251
248 Vector3 originalPosition = objectGroup.AbsolutePosition; 252 // Make sure all bits but the ones we want are clear
253 // on take.
254 // This will be applied to the current perms, so
255 // it will do what we want.
256 objectGroup.RootPart.NextOwnerMask &=
257 ((uint)PermissionMask.Copy |
258 (uint)PermissionMask.Transfer |
259 (uint)PermissionMask.Modify);
260 objectGroup.RootPart.NextOwnerMask |=
261 (uint)PermissionMask.Move;
249 262
250 objectGroup.AbsolutePosition = inventoryStoredPosition; 263 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
251 264
252 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); 265 objectGroup.AbsolutePosition = originalPosition;
253 266
254 objectGroup.AbsolutePosition = originalPosition; 267 xmlStrings[objectGroup.UUID] = sceneObjectXml;
268 }
255 269
256 // Get the user info of the item destination 270 string itemXml;
257 //
258 UUID userID = UUID.Zero;
259 271
260 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || 272 if (objlist.Count > 1)
261 action == DeRezAction.SaveToExistingUserInventoryItem) 273 {
262 { 274 float minX, minY, minZ;
263 // Take or take copy require a taker 275 float maxX, maxY, maxZ;
264 // Saving changes requires a local user
265 //
266 if (remoteClient == null)
267 return UUID.Zero;
268 276
269 userID = remoteClient.AgentId; 277 Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist,
270 } 278 out minX, out maxX, out minY, out maxY,
271 else 279 out minZ, out maxZ);
272 {
273 // All returns / deletes go to the object owner
274 //
275 280
276 userID = objectGroup.RootPart.OwnerID; 281 // CreateWrapper
277 } 282 XmlDocument itemDoc = new XmlDocument();
283 XmlElement root = itemDoc.CreateElement("", "CoalescedObject", "");
284 itemDoc.AppendChild(root);
278 285
279 if (userID == UUID.Zero) // Can't proceed 286 // Embed the offsets into the group XML
280 { 287 for ( int i = 0 ; i < objlist.Count ; i++ )
281 return UUID.Zero; 288 {
282 } 289 XmlDocument doc = new XmlDocument();
290 SceneObjectGroup g = objlist[i];
291 doc.LoadXml(xmlStrings[g.UUID]);
292 XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup");
293 e.SetAttribute("offsetx", offsets[i].X.ToString());
294 e.SetAttribute("offsety", offsets[i].Y.ToString());
295 e.SetAttribute("offsetz", offsets[i].Z.ToString());
296
297 XmlNode objectNode = itemDoc.ImportNode(e, true);
298 root.AppendChild(objectNode);
299 }
283 300
284 // If we're returning someone's item, it goes back to the 301 float sizeX = maxX - minX;
285 // owner's Lost And Found folder. 302 float sizeY = maxY - minY;
286 // Delete is treated like return in this case 303 float sizeZ = maxZ - minZ;
287 // Deleting your own items makes them go to trash
288 //
289 304
290 InventoryFolderBase folder = null; 305 root.SetAttribute("x", sizeX.ToString());
291 InventoryItemBase item = null; 306 root.SetAttribute("y", sizeY.ToString());
307 root.SetAttribute("z", sizeZ.ToString());
292 308
293 if (DeRezAction.SaveToExistingUserInventoryItem == action) 309 itemXml = itemDoc.InnerXml;
294 { 310 }
295 item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID); 311 else
296 item = m_Scene.InventoryService.GetItem(item); 312 {
313 itemXml = xmlStrings[objlist[0].UUID];
314 }
315
316 // Get the user info of the item destination
317 //
318 UUID userID = UUID.Zero;
319
320 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
321 action == DeRezAction.SaveToExistingUserInventoryItem)
322 {
323 // Take or take copy require a taker
324 // Saving changes requires a local user
325 //
326 if (remoteClient == null)
327 return UUID.Zero;
328
329 userID = remoteClient.AgentId;
330 }
331 else
332 {
333 // All returns / deletes go to the object owner
334 //
297 335
298 //item = userInfo.RootFolder.FindItem( 336 userID = objlist[0].RootPart.OwnerID;
299 // objectGroup.RootPart.FromUserInventoryItemID); 337 }
300 338
301 if (null == item) 339 if (userID == UUID.Zero) // Can't proceed
302 { 340 {
303 m_log.DebugFormat(
304 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
305 objectGroup.Name, objectGroup.UUID);
306 return UUID.Zero; 341 return UUID.Zero;
307 } 342 }
308 } 343
309 else 344 // If we're returning someone's item, it goes back to the
310 { 345 // owner's Lost And Found folder.
311 // Folder magic 346 // Delete is treated like return in this case
347 // Deleting your own items makes them go to trash
312 // 348 //
313 if (action == DeRezAction.Delete) 349
350 InventoryFolderBase folder = null;
351 InventoryItemBase item = null;
352
353 if (DeRezAction.SaveToExistingUserInventoryItem == action)
314 { 354 {
315 // Deleting someone else's item 355 item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID);
316 // 356 item = m_Scene.InventoryService.GetItem(item);
317 if (remoteClient == null ||
318 objectGroup.OwnerID != remoteClient.AgentId)
319 {
320 357
321 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 358 //item = userInfo.RootFolder.FindItem(
322 } 359 // objectGroup.RootPart.FromUserInventoryItemID);
323 else 360
361 if (null == item)
324 { 362 {
325 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); 363 m_log.DebugFormat(
364 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
365 objlist[0].Name, objlist[0].UUID);
366 return UUID.Zero;
326 } 367 }
327 } 368 }
328 else if (action == DeRezAction.Return) 369 else
329 { 370 {
330 371 // Folder magic
331 // Dump to lost + found unconditionally
332 // 372 //
333 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
334 }
335
336 if (folderID == UUID.Zero && folder == null)
337 {
338 if (action == DeRezAction.Delete) 373 if (action == DeRezAction.Delete)
339 { 374 {
340 // Deletes go to trash by default 375 // Deleting someone else's item
341 // 376 //
342 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
343 }
344 else
345 {
346 if (remoteClient == null || 377 if (remoteClient == null ||
347 objectGroup.OwnerID != remoteClient.AgentId) 378 objlist[0].OwnerID != remoteClient.AgentId)
348 { 379 {
349 // Taking copy of another person's item. Take to 380
350 // Objects folder. 381 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
351 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
352 } 382 }
353 else 383 else
354 { 384 {
355 // Catch all. Use lost & found 385 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
386 }
387 }
388 else if (action == DeRezAction.Return)
389 {
390
391 // Dump to lost + found unconditionally
392 //
393 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
394 }
395
396 if (folderID == UUID.Zero && folder == null)
397 {
398 if (action == DeRezAction.Delete)
399 {
400 // Deletes go to trash by default
356 // 401 //
402 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
403 }
404 else
405 {
406 if (remoteClient == null ||
407 objlist[0].OwnerID != remoteClient.AgentId)
408 {
409 // Taking copy of another person's item. Take to
410 // Objects folder.
411 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
412 }
413 else
414 {
415 // Catch all. Use lost & found
416 //
357 417
358 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); 418 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
419 }
359 } 420 }
360 } 421 }
361 }
362 422
363 // Override and put into where it came from, if it came 423 // Override and put into where it came from, if it came
364 // from anywhere in inventory 424 // from anywhere in inventory
365 // 425 //
366 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) 426 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
367 {
368 if (objectGroup.RootPart.FromFolderID != UUID.Zero)
369 { 427 {
370 InventoryFolderBase f = new InventoryFolderBase(objectGroup.RootPart.FromFolderID, userID); 428 if (objlist[0].RootPart.FromFolderID != UUID.Zero)
371 folder = m_Scene.InventoryService.GetFolder(f); 429 {
430 InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID);
431 folder = m_Scene.InventoryService.GetFolder(f);
432 }
372 } 433 }
373 }
374 434
375 if (folder == null) // None of the above 435 if (folder == null) // None of the above
376 { 436 {
377 folder = new InventoryFolderBase(folderID); 437 folder = new InventoryFolderBase(folderID);
378 438
379 if (folder == null) // Nowhere to put it 439 if (folder == null) // Nowhere to put it
440 {
441 return UUID.Zero;
442 }
443 }
444
445 item = new InventoryItemBase();
446 // Can't know creator is the same, so null it in inventory
447 if (objlist.Count > 1)
448 item.CreatorId = UUID.Zero.ToString();
449 else
450 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
451 item.ID = UUID.Random();
452 item.InvType = (int)InventoryType.Object;
453 item.Folder = folder.ID;
454 item.Owner = userID;
455 if (objlist.Count > 1)
380 { 456 {
381 return UUID.Zero; 457 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
458 }
459 else
460 {
461 item.SaleType = objlist[0].RootPart.ObjectSaleType;
462 item.SalePrice = objlist[0].RootPart.SalePrice;
382 } 463 }
383 } 464 }
384 465
385 item = new InventoryItemBase(); 466 AssetBase asset = CreateAsset(
386 item.CreatorId = objectGroup.RootPart.CreatorID.ToString(); 467 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
387 item.CreatorData = objectGroup.RootPart.CreatorData; 468 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
388 item.ID = UUID.Random(); 469 (sbyte)AssetType.Object,
389 item.InvType = (int)InventoryType.Object; 470 Utils.StringToBytes(itemXml),
390 item.Folder = folder.ID; 471 objlist[0].OwnerID.ToString());
391 item.Owner = userID; 472 m_Scene.AssetService.Store(asset);
392 } 473 assetID = asset.FullID;
393
394 AssetBase asset = CreateAsset(
395 objectGroup.GetPartName(objectGroup.RootPart.LocalId),
396 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId),
397 (sbyte)AssetType.Object,
398 Utils.StringToBytes(sceneObjectXml),
399 objectGroup.OwnerID.ToString());
400 m_Scene.AssetService.Store(asset);
401 assetID = asset.FullID;
402
403 if (DeRezAction.SaveToExistingUserInventoryItem == action)
404 {
405 item.AssetID = asset.FullID;
406 m_Scene.InventoryService.UpdateItem(item);
407 }
408 else
409 {
410 item.AssetID = asset.FullID;
411 474
412 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 475 if (DeRezAction.SaveToExistingUserInventoryItem == action)
413 { 476 {
414 uint perms = objectGroup.GetEffectivePermissions(); 477 item.AssetID = asset.FullID;
415 uint nextPerms = (perms & 7) << 13; 478 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 } 479 }
442 else 480 else
443 { 481 {
444 item.BasePermissions = objectGroup.GetEffectivePermissions(); 482 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 483
450 item.CurrentPermissions &= 484 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7;
451 ((uint)PermissionMask.Copy | 485 foreach (SceneObjectGroup grp in objlist)
452 (uint)PermissionMask.Transfer | 486 effectivePerms &= grp.GetEffectivePermissions();
453 (uint)PermissionMask.Modify | 487 effectivePerms |= (uint)PermissionMask.Move;
454 (uint)PermissionMask.Move |
455 7); // Preserve folded permissions
456 }
457 488
458 // TODO: add the new fields (Flags, Sale info, etc) 489 if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
459 item.CreationDate = Util.UnixTimeSinceEpoch(); 490 {
460 item.Description = asset.Description; 491 uint perms = effectivePerms;
461 item.Name = asset.Name; 492 uint nextPerms = (perms & 7) << 13;
462 item.AssetType = asset.Type; 493 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
494 perms &= ~(uint)PermissionMask.Copy;
495 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
496 perms &= ~(uint)PermissionMask.Transfer;
497 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
498 perms &= ~(uint)PermissionMask.Modify;
499
500 item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask;
501 item.CurrentPermissions = item.BasePermissions;
502 item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask;
503 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask;
504 item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask;
505
506 // Magic number badness. Maybe this deserves an enum.
507 // bit 4 (16) is the "Slam" bit, it means treat as passed
508 // and apply next owner perms on rez
509 item.CurrentPermissions |= 16; // Slam!
510 }
511 else
512 {
513 item.BasePermissions = effectivePerms;
514 item.CurrentPermissions = effectivePerms;
515 item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms;
516 item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms;
517 item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms;
518
519 item.CurrentPermissions &=
520 ((uint)PermissionMask.Copy |
521 (uint)PermissionMask.Transfer |
522 (uint)PermissionMask.Modify |
523 (uint)PermissionMask.Move |
524 7); // Preserve folded permissions
525 }
463 526
464 m_Scene.AddInventoryItem(item); 527 item.CreationDate = Util.UnixTimeSinceEpoch();
528 item.Description = asset.Description;
529 item.Name = asset.Name;
530 item.AssetType = asset.Type;
465 531
466 if (remoteClient != null && item.Owner == remoteClient.AgentId) 532 m_Scene.AddInventoryItem(item);
467 { 533
468 remoteClient.SendInventoryItemCreateUpdate(item, 0); 534 if (remoteClient != null && item.Owner == remoteClient.AgentId)
469 }
470 else
471 {
472 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
473 if (notifyUser != null)
474 { 535 {
475 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); 536 remoteClient.SendInventoryItemCreateUpdate(item, 0);
537 }
538 else
539 {
540 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
541 if (notifyUser != null)
542 {
543 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
544 }
476 } 545 }
477 } 546 }
478 } 547 }
479
480 return assetID; 548 return assetID;
481 } 549 }
482 550
@@ -484,8 +552,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
484 /// <summary> 552 /// <summary>
485 /// Rez an object into the scene from the user's inventory 553 /// Rez an object into the scene from the user's inventory
486 /// </summary> 554 /// </summary>
555 /// <remarks>
487 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing 556 /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing
488 /// things to the scene. The caller should be doing that, I think. 557 /// things to the scene. The caller should be doing that, I think.
558 /// </remarks>
489 /// <param name="remoteClient"></param> 559 /// <param name="remoteClient"></param>
490 /// <param name="itemID"></param> 560 /// <param name="itemID"></param>
491 /// <param name="RayEnd"></param> 561 /// <param name="RayEnd"></param>
@@ -502,21 +572,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
502 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 572 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
503 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 573 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
504 { 574 {
505 // Work out position details 575// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
506 byte bRayEndIsIntersection = (byte)0; 576
507 577 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
508 if (RayEndIsIntersection)
509 {
510 bRayEndIsIntersection = (byte)1;
511 }
512 else
513 {
514 bRayEndIsIntersection = (byte)0;
515 }
516
517 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); 578 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
518
519
520 Vector3 pos = m_Scene.GetNewRezLocation( 579 Vector3 pos = m_Scene.GetNewRezLocation(
521 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 580 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
522 BypassRayCast, bRayEndIsIntersection, true, scale, false); 581 BypassRayCast, bRayEndIsIntersection, true, scale, false);
@@ -531,6 +590,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
531 590
532 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); 591 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
533 592
593 SceneObjectGroup group = null;
594
534 if (rezAsset != null) 595 if (rezAsset != null)
535 { 596 {
536 UUID itemId = UUID.Zero; 597 UUID itemId = UUID.Zero;
@@ -539,34 +600,78 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
539 // item that it came from. This allows us to enable 'save object to inventory' 600 // item that it came from. This allows us to enable 'save object to inventory'
540 if (!m_Scene.Permissions.BypassPermissions()) 601 if (!m_Scene.Permissions.BypassPermissions())
541 { 602 {
542 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) 603 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
543 { 604 {
544 itemId = item.ID; 605 itemId = item.ID;
545 } 606 }
546 } 607 }
547 else 608 else
548 { 609 {
549 // Brave new fullperm world 610 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
550 // 611 {
551 itemId = item.ID; 612 // Brave new fullperm world
613 itemId = item.ID;
614 }
552 } 615 }
553 616
554 string xmlData = Utils.BytesToString(rezAsset.Data); 617 string xmlData = Utils.BytesToString(rezAsset.Data);
555 SceneObjectGroup group 618 List<SceneObjectGroup> objlist =
556 = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); 619 new List<SceneObjectGroup>();
620 List<Vector3> veclist = new List<Vector3>();
621
622 XmlDocument doc = new XmlDocument();
623 doc.LoadXml(xmlData);
624 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
625 if (e == null || attachment) // Single
626 {
627 SceneObjectGroup g =
628 SceneObjectSerializer.FromOriginalXmlFormat(
629 itemId, xmlData);
630 objlist.Add(g);
631 veclist.Add(new Vector3(0, 0, 0));
557 632
558 Util.FireAndForget(delegate { AddUserData(group); }); 633 float offsetHeight = 0;
559 634 pos = m_Scene.GetNewRezLocation(
560 group.RootPart.FromFolderID = item.Folder; 635 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
636 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false);
637 pos.Z += offsetHeight;
638 }
639 else
640 {
641 XmlElement coll = (XmlElement)e;
642 float bx = Convert.ToSingle(coll.GetAttribute("x"));
643 float by = Convert.ToSingle(coll.GetAttribute("y"));
644 float bz = Convert.ToSingle(coll.GetAttribute("z"));
645 Vector3 bbox = new Vector3(bx, by, bz);
561 646
562 // If it's rezzed in world, select it. Much easier to 647 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
563 // find small items. 648 RayTargetID, Quaternion.Identity,
564 // 649 BypassRayCast, bRayEndIsIntersection, true,
565 if (!attachment) 650 bbox, false);
566 group.RootPart.CreateSelected = true; 651
652 pos -= bbox / 2;
653
654 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
655 foreach (XmlNode n in groups)
656 {
657 SceneObjectGroup g =
658 SceneObjectSerializer.FromOriginalXmlFormat(
659 itemId, n.OuterXml);
660 objlist.Add(g);
661 XmlElement el = (XmlElement)n;
662 float x = Convert.ToSingle(el.GetAttribute("offsetx"));
663 float y = Convert.ToSingle(el.GetAttribute("offsety"));
664 float z = Convert.ToSingle(el.GetAttribute("offsetz"));
665 veclist.Add(new Vector3(x, y, z));
666 }
667 }
668
669 int primcount = 0;
670 foreach (SceneObjectGroup g in objlist)
671 primcount += g.PrimCount;
567 672
568 if (!m_Scene.Permissions.CanRezObject( 673 if (!m_Scene.Permissions.CanRezObject(
569 group.PrimCount, remoteClient.AgentId, pos) 674 primcount, remoteClient.AgentId, pos)
570 && !attachment) 675 && !attachment)
571 { 676 {
572 // The client operates in no fail mode. It will 677 // The client operates in no fail mode. It will
@@ -579,131 +684,131 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
579 return null; 684 return null;
580 } 685 }
581 686
582 group.ResetIDs(); 687 for (int i = 0 ; i < objlist.Count ; i++ )
583
584 if (attachment)
585 { 688 {
586 group.RootPart.Flags |= PrimFlags.Phantom; 689 group = objlist[i];
587 group.RootPart.IsAttachment = true; 690
691 Vector3 storedPosition = group.AbsolutePosition;
692 if (group.UUID == UUID.Zero)
693 {
694 m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3");
695 }
696 group.RootPart.FromFolderID = item.Folder;
697
698 // If it's rezzed in world, select it. Much easier to
699 // find small items.
700 //
701 if (!attachment)
702 {
703 group.RootPart.CreateSelected = true;
704 foreach (SceneObjectPart child in group.Parts)
705 child.CreateSelected = true;
706 }
707 group.ResetIDs();
708
709 if (attachment)
710 {
711 group.RootPart.Flags |= PrimFlags.Phantom;
712 group.RootPart.IsAttachment = true;
713 }
588 714
589 // If we're rezzing an attachment then don't ask 715 // If we're rezzing an attachment then don't ask
590 // AddNewSceneObject() to update the client since 716 // AddNewSceneObject() to update the client since
591 // we'll be doing that later on. Scheduling more 717 // we'll be doing that later on. Scheduling more than
592 // than one full update during the attachment 718 // one full update during the attachment
593 // process causes some clients to fail to display 719 // process causes some clients to fail to display the
594 // the attachment properly. 720 // attachment properly.
595 // Also, don't persist attachments.
596 m_Scene.AddNewSceneObject(group, false, false);
597 }
598 else
599 {
600 m_Scene.AddNewSceneObject(group, true, false); 721 m_Scene.AddNewSceneObject(group, true, false);
601 }
602 722
603 // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); 723 // if attachment we set it's asset id so object updates
604 // if attachment we set it's asset id so object updates can reflect that 724 // can reflect that, if not, we set it's position in world.
605 // if not, we set it's position in world. 725 if (!attachment)
606 if (!attachment) 726 {
607 { 727 group.ScheduleGroupForFullUpdate();
608 group.ScheduleGroupForFullUpdate(); 728
609 729 group.AbsolutePosition = pos + veclist[i];
610 float offsetHeight = 0; 730 }
611 pos = m_Scene.GetNewRezLocation( 731 else
612 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 732 {
613 BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); 733 group.SetFromItemID(itemID);
614 pos.Z += offsetHeight; 734 }
615 group.AbsolutePosition = pos;
616 // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight);
617
618 }
619 else
620 {
621 group.SetFromItemID(itemID);
622 }
623 735
624 SceneObjectPart rootPart = null; 736 SceneObjectPart rootPart = null;
625 try
626 {
627 rootPart = group.GetChildPart(group.UUID);
628 }
629 catch (NullReferenceException)
630 {
631 string isAttachment = "";
632 737
633 if (attachment) 738 try
634 isAttachment = " Object was an attachment"; 739 {
740 rootPart = group.GetChildPart(group.UUID);
741 }
742 catch (NullReferenceException)
743 {
744 string isAttachment = "";
635 745
636 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); 746 if (attachment)
637 } 747 isAttachment = " Object was an attachment";
638 748
639 // Since renaming the item in the inventory does not affect the name stored 749 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
640 // in the serialization, transfer the correct name from the inventory to the 750 }
641 // object itself before we rez.
642 rootPart.Name = item.Name;
643 rootPart.Description = item.Description;
644 751
645 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0) 752 // Since renaming the item in the inventory does not
646 { 753 // affect the name stored in the serialization, transfer
754 // the correct name from the inventory to the
755 // object itself before we rez.
756 rootPart.Name = item.Name;
757 rootPart.Description = item.Description;
647 rootPart.ObjectSaleType = item.SaleType; 758 rootPart.ObjectSaleType = item.SaleType;
648 rootPart.SalePrice = item.SalePrice; 759 rootPart.SalePrice = item.SalePrice;
649 }
650
651 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
652 if ((rootPart.OwnerID != item.Owner) ||
653 (item.CurrentPermissions & 16) != 0 || // Magic number
654 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
655 {
656 //Need to kill the for sale here
657 rootPart.ObjectSaleType = 0;
658 rootPart.SalePrice = 10;
659 760
660 if (m_Scene.Permissions.PropagatePermissions()) 761 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
762 if ((rootPart.OwnerID != item.Owner) ||
763 (item.CurrentPermissions & 16) != 0)
661 { 764 {
662 foreach (SceneObjectPart part in group.Parts) 765 //Need to kill the for sale here
766 rootPart.ObjectSaleType = 0;
767 rootPart.SalePrice = 10;
768
769 if (m_Scene.Permissions.PropagatePermissions())
663 { 770 {
664 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 771 foreach (SceneObjectPart part in group.Parts)
665 part.EveryoneMask = item.EveryOnePermissions; 772 {
666 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 773 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
667 part.NextOwnerMask = item.NextPermissions; 774 {
668 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 775 part.EveryoneMask = item.EveryOnePermissions;
669 part.GroupMask = item.GroupPermissions; 776 part.NextOwnerMask = item.NextPermissions;
777 }
778 part.GroupMask = 0; // DO NOT propagate here
779 }
780
781 group.ApplyNextOwnerPermissions();
670 } 782 }
671
672 group.ApplyNextOwnerPermissions();
673 } 783 }
674 }
675 784
676 foreach (SceneObjectPart part in group.Parts) 785 foreach (SceneObjectPart part in group.Parts)
677 {
678 if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
679 { 786 {
680 part.LastOwnerID = part.OwnerID; 787 if ((part.OwnerID != item.Owner) ||
681 part.OwnerID = item.Owner; 788 (item.CurrentPermissions & 16) != 0)
682 part.Inventory.ChangeInventoryOwner(item.Owner); 789 {
683 part.GroupMask = 0; // DO NOT propagate here 790 part.LastOwnerID = part.OwnerID;
684 } 791 part.OwnerID = item.Owner;
685 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 792 part.Inventory.ChangeInventoryOwner(item.Owner);
793 part.GroupMask = 0; // DO NOT propagate here
794 }
686 part.EveryoneMask = item.EveryOnePermissions; 795 part.EveryoneMask = item.EveryOnePermissions;
687 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
688 part.NextOwnerMask = item.NextPermissions; 796 part.NextOwnerMask = item.NextPermissions;
689 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 797 }
690 part.GroupMask = item.GroupPermissions;
691 }
692 798
693 rootPart.TrimPermissions(); 799 rootPart.TrimPermissions();
694 800
695 if (!attachment) 801 if (!attachment)
696 {
697 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
698 { 802 {
699 group.ClearPartAttachmentData(); 803 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
700 } 804 group.ClearPartAttachmentData();
701 805
702 // Fire on_rez 806 // Fire on_rez
703 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); 807 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
704 rootPart.ParentGroup.ResumeScripts(); 808 rootPart.ParentGroup.ResumeScripts();
705 809
706 rootPart.ScheduleFullUpdate(); 810 rootPart.ScheduleFullUpdate();
811 }
707 } 812 }
708 813
709 if (!m_Scene.Permissions.BypassPermissions()) 814 if (!m_Scene.Permissions.BypassPermissions())
@@ -721,9 +826,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
721 } 826 }
722 } 827 }
723 } 828 }
724
725 return rootPart.ParentGroup;
726 } 829 }
830 return group;
727 } 831 }
728 832
729 return null; 833 return null;