diff options
author | BlueWall | 2011-04-13 09:53:44 -0400 |
---|---|---|
committer | BlueWall | 2011-04-13 09:53:44 -0400 |
commit | d3457eae7a33f01a8fa906c4040792cdc4a67857 (patch) | |
tree | f92e60733b8397576b86c486e05aa5219f27d034 /OpenSim/Region/CoreModules/Framework | |
parent | Merge branch 'master' of /home/opensim/src/OpenSim/Core (diff) | |
parent | Move example HttpProxy setting to OpenSim.ini.example and tidy (diff) | |
download | opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.zip opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.gz opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.bz2 opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.xz |
Merge branch 'master' of /home/git/repo/OpenSim
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 754 |
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 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Net; | 30 | using System.Net; |
31 | using System.Xml; | ||
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Threading; | 33 | using 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; |