/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List <ISceneEntity> objectGroups, UUID AgentId, bool permissionToDelete, bool permissionToTake) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.agentId = AgentId; dtis.permissionToDelete = permissionToDelete; dtis.permissionToTake = permissionToTake; //Do this before the locking so that the objects 'appear' gone and the client doesn't think things have gone wrong if (permissionToDelete) { DeleteGroups(objectGroups); } lock (m_removeFromSimQueue) { m_removeFromSimQueue.Enqueue(dtis); } if (!DeleteLoopInUse) { DeleteLoopInUse = true; //m_log.Debug("[SCENE]: Starting delete loop"); Util.FireAndForget(DoDeleteObject, new Object[] { 0 }); } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List <ISceneEntity> objectGroups, UUID agentId, bool permissionToDelete, bool permissionToTake) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder { action = action, folderID = folderID, objectGroups = objectGroups, agentId = agentId, permissionToDelete = permissionToDelete, permissionToTake = permissionToTake }; //Do this before the locking so that the objects 'appear' gone and the client doesn't think things have gone wrong if (permissionToDelete) { DeleteGroups(objectGroups); } m_removeFromSimQueue.Enqueue(dtis); if (!DeleteLoopInUse) { DeleteLoopInUse = true; //MainConsole.Instance.Debug("[SCENE]: Starting delete loop"); Util.FireAndForget(DoDeleteObject); } }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient) { // HACK: This is only working for lists containing a single item! // It's just a hack to make this WIP compile and run. Nothing // currently calls this with multiple items. UUID ret = UUID.Zero; Dictionary <UUID, List <SceneObjectGroup> > deletes = new Dictionary <UUID, List <SceneObjectGroup> >(); foreach (SceneObjectGroup g in objectGroups) { if (!deletes.ContainsKey(g.OwnerID)) { deletes[g.OwnerID] = new List <SceneObjectGroup>(); } deletes[g.OwnerID].Add(g); } foreach (List <SceneObjectGroup> objlist in deletes.Values) { foreach (SceneObjectGroup g in objlist) { ret = DeleteToInventory(action, folderID, g, remoteClient); } } return(ret); }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) { m_inventoryTicker.Stop(); } lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroup = objectGroup; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) { m_inventoryTicker.Start(); } // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) { objectGroup.DeleteGroup(false); } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) lock (m_inventoryTicker) m_inventoryTicker.Stop(); lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroup = objectGroup; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) lock (m_inventoryTicker) m_inventoryTicker.Start(); // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) objectGroup.DeleteGroup(false); }
/// <summary> /// Delete a scene object asynchronously /// </summary> /// <param name="scene"></param> /// <param name="part"></param> /// <param name="action"></param> /// <param name="destinationId"></param> /// <param name="client"></param> public static void DeleteSceneObjectAsync( TestScene scene, SceneObjectPart part, DeRezAction action, UUID destinationId, IClientAPI client) { // Turn off the timer on the async sog deleter - we'll crank it by hand within a unit test AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; sogd.Enabled = false; scene.DeRezObject(client, part.LocalId, UUID.Zero, action, destinationId); sogd.InventoryDeQueueAndDelete(); }
/// /// DeleteToInventory /// public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient) { UUID ret = UUID.Zero; // HACK: Only works for lists of length one. // Intermediate version, just to make things compile foreach (SceneObjectGroup g in objectGroups) { ret = DeleteToInventory(action, folderID, g, remoteClient); } return(ret); }
/// /// DeleteToInventory /// public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient); if (!assetID.Equals(UUID.Zero)) { UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); } else { m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); } return(assetID); }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient) { // HACK: This is only working for lists containing a single item! // It's just a hack to make this WIP compile and run. Nothing // currently calls this with multiple items. UUID ret = UUID.Zero; foreach (SceneObjectGroup g in objectGroups) { ret = DeleteToInventory(action, folderID, g, remoteClient); } return(ret); }
public virtual List <InventoryItemBase> CopyToInventory( DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment) { List <InventoryItemBase> copiedItems = new List <InventoryItemBase>(); Dictionary <UUID, List <SceneObjectGroup> > bundlesToCopy = new Dictionary <UUID, List <SceneObjectGroup> >(); if (CoalesceMultipleObjectsToInventory) { // The following code groups the SOG's by owner. No objects // belonging to different people can be coalesced, for obvious // reasons. foreach (SceneObjectGroup g in objectGroups) { if (!bundlesToCopy.ContainsKey(g.OwnerID)) { bundlesToCopy[g.OwnerID] = new List <SceneObjectGroup>(); } bundlesToCopy[g.OwnerID].Add(g); } } else { // If we don't want to coalesce then put every object in its own bundle. foreach (SceneObjectGroup g in objectGroups) { List <SceneObjectGroup> bundle = new List <SceneObjectGroup>(); bundle.Add(g); bundlesToCopy[g.UUID] = bundle; } } // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}", // bundlesToCopy.Count, folderID, action, remoteClient.Name); // Each iteration is really a separate asset being created, // with distinct destinations as well. foreach (List <SceneObjectGroup> bundle in bundlesToCopy.Values) { copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); } return(copiedItems); }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, IEnumerable <SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) { m_inventoryTicker.Stop(); } lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = new List <SceneObjectGroup>(objectGroups); if (dtis.objectGroups.Count == 0) { //something is wrong, caller sent us an empty set throw new ArgumentException("DeleteToInventory() Can not work with an empty set", "objectGroups"); } dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) { m_inventoryTicker.Start(); } // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) { foreach (SceneObjectGroup group in objectGroups) { group.DeleteGroup(false); } } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) { lock (m_inventoryTicker) m_inventoryTicker.Stop(); } lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) { lock (m_inventoryTicker) m_inventoryTicker.Start(); } // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) { List <uint> killIDs = new List <uint>(); foreach (SceneObjectGroup g in objectGroups) { killIDs.Add(g.LocalId); g.DeleteGroupFromScene(true); } m_scene.SendKillObject(killIDs); } }
public virtual UUID CopyToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient) { Dictionary <UUID, List <SceneObjectGroup> > bundlesToCopy = new Dictionary <UUID, List <SceneObjectGroup> >(); if (CoalesceMultipleObjectsToInventory) { // The following code groups the SOG's by owner. No objects // belonging to different people can be coalesced, for obvious // reasons. foreach (SceneObjectGroup g in objectGroups) { if (!bundlesToCopy.ContainsKey(g.OwnerID)) { bundlesToCopy[g.OwnerID] = new List <SceneObjectGroup>(); } bundlesToCopy[g.OwnerID].Add(g); } } else { // If we don't want to coalesce then put every object in its own bundle. foreach (SceneObjectGroup g in objectGroups) { List <SceneObjectGroup> bundle = new List <SceneObjectGroup>(); bundle.Add(g); bundlesToCopy[g.UUID] = bundle; } } // This is method scoped and will be returned. It will be the // last created asset id UUID assetID = UUID.Zero; // Each iteration is really a separate asset being created, // with distinct destinations as well. foreach (List <SceneObjectGroup> bundle in bundlesToCopy.Values) { assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient); } return(assetID); }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, IEnumerable<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) m_inventoryTicker.Stop(); lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = new List<SceneObjectGroup>(objectGroups); if (dtis.objectGroups.Count == 0) { //something is wrong, caller sent us an empty set throw new ArgumentException("DeleteToInventory() Can not work with an empty set", "objectGroups"); } dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) m_inventoryTicker.Start(); // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) { foreach (SceneObjectGroup group in objectGroups) { group.DeleteGroup(false); } } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, UUID AgentId, bool permissionToDelete, bool permissionToTake) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.agentId = AgentId; dtis.permissionToDelete = permissionToDelete; dtis.permissionToTake = permissionToTake; //Do this before the locking so that the objects 'appear' gone and the client doesn't think things have gone wrong if (permissionToDelete) { m_scene.DeleteGroups(objectGroups); } lock (m_sendToInventoryQueue) { m_sendToInventoryQueue.Enqueue(dtis); } lock (m_removeFromSimQueue) { m_removeFromSimQueue.Enqueue(dtis); } if (!DeleteLoopInUse) { DeleteLoopInUse = true; //m_log.Debug("[SCENE]: Starting delete loop"); Util.FireAndForget(DoDeleteObject, new Object[] { 0 }); } if (!SendToInventoryLoopInUse) { SendToInventoryLoopInUse = true; //m_log.Debug("[SCENE]: Starting send to inventory loop"); Util.FireAndForget(DoSendToInventory, new Object[] { 0 }); } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) lock (m_inventoryTicker) m_inventoryTicker.Stop(); lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (Enabled) lock (m_inventoryTicker) m_inventoryTicker.Start(); // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object // has gone to inventory, it will reappear in the region again on restart instead of being lost. // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) { List<uint> killIDs = new List<uint>(); foreach (SceneObjectGroup g in objectGroups) { killIDs.Add(g.LocalId); g.DeleteGroupFromScene(true); } m_scene.SendKillObject(killIDs); } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); if (permissionToDelete) { foreach (SceneObjectGroup g in objectGroups) { g.DeleteGroupFromScene(false); } } if (Monitor.TryEnter(m_threadLock)) { if (!m_running) { if (Enabled) { m_running = true; Util.FireAndForget(x => InventoryDeQueueAndDelete()); } else { m_running = true; InventoryDeQueueAndDelete(); } } Monitor.Exit(m_threadLock); } }
// DO NOT OVERRIDE THE BASE METHOD public new virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = base.DeleteToInventory(action, folderID, new List <SceneObjectGroup>() { objectGroup }, remoteClient); if (!assetID.Equals(UUID.Zero)) { if (remoteClient != null) { UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); } } else { m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); } return(assetID); }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List <SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) { lock (m_inventoryTicker) m_inventoryTicker.Stop(); } lock (m_inventoryDeletes) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; m_inventoryDeletes.Enqueue(dtis); } if (permissionToDelete) { foreach (SceneObjectGroup g in objectGroups) { g.DeleteGroupFromScene(false); } } if (Enabled) { lock (m_inventoryTicker) m_inventoryTicker.Start(); } }
private DeRezActionResult GetIntendedResult(DeRezAction action) { switch (action) { case DeRezAction.SaveToExistingUserInventoryItem: return DeRezActionResult.Take; case DeRezAction.TakeCopy: return DeRezActionResult.Take; case DeRezAction.GodTakeCopy: return DeRezActionResult.Take; case DeRezAction.Take: return DeRezActionResult.Both; case DeRezAction.Delete: return DeRezActionResult.Both; case DeRezAction.Return: return DeRezActionResult.Both; } return DeRezActionResult.None; }
private DeRezActionResult FindDeRezPermissions(IClientAPI remoteClient, SceneObjectGroup grp, DeRezAction action) { bool permissionToTake = false; bool permissionToDelete = false; switch (action) { case DeRezAction.SaveToExistingUserInventoryItem: if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) { permissionToTake = true; permissionToDelete = false; } break; case DeRezAction.TakeCopy: permissionToTake = Permissions.CanTakeCopyObject( grp.UUID, remoteClient.AgentId); break; case DeRezAction.GodTakeCopy: permissionToTake = Permissions.IsGod( remoteClient.AgentId); break; case DeRezAction.Take: permissionToTake = Permissions.CanTakeObject( grp.UUID, remoteClient.AgentId); //If they can take, they can delete! permissionToDelete = permissionToTake; break; case DeRezAction.Delete: permissionToTake = Permissions.CanDeleteObject( grp.UUID, remoteClient.AgentId); permissionToDelete = permissionToTake; break; case DeRezAction.Return: if (remoteClient != null) { permissionToTake = Permissions.CanReturnObject( grp.UUID, remoteClient.AgentId); permissionToDelete = permissionToTake; if (permissionToDelete) { UUID NotifyID = (grp.OwnerID == grp.GroupID) ? grp.RootPart.LastOwnerID : grp.OwnerID; AddReturn(NotifyID, grp.Name, grp.AbsolutePosition, "parcel owner return"); } } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } break; default: m_log.DebugFormat( "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name); return DeRezActionResult.None; } if (permissionToTake && permissionToDelete) { return DeRezActionResult.Both; } else if (permissionToTake) { return DeRezActionResult.Take; } else if (permissionToDelete) { return DeRezActionResult.Delete; } return DeRezActionResult.None; }
/// /// DeleteToInventory /// public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) { UUID ret = UUID.Zero; // HACK: Only works for lists of length one. // Intermediate version, just to make things compile foreach (SceneObjectGroup g in objectGroups) ret = DeleteToInventory(action, folderID, g, remoteClient); return ret; }
/// <summary> /// Called when an object is removed from the environment into inventory. /// </summary> /// <param name="remoteClient"></param> /// <param name="localID"></param> /// <param name="groupID"></param> /// <param name="action"></param> /// <param name="destinationID"></param> public virtual void DeRezObject(IClientAPI remoteClient, uint localID, UUID groupID, DeRezAction action, UUID destinationID) { DeRezObjects(remoteClient, new List<uint>() { localID} , groupID, action, destinationID); }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, IEnumerable<SceneObjectGroup> objectGroups, IClientAPI remoteClient) { StringBuilder objectNames = new StringBuilder(); foreach (var obj in objectGroups) { objectNames.Append(obj.Name); objectNames.Append(", "); } string agentText = "(unknown/internal)"; if (remoteClient != null) agentText = remoteClient.AgentId.ToString(); m_log.InfoFormat("[AGENT INVENTORY] About to DeRezAction.{0} for client {1}. Groups: {2}", action, agentText, objectNames.ToString()); //now lets deal with the individual cases.. switch (action) { case DeRezAction.Delete: this.PerformInventoryDelete(folderID, objectGroups, remoteClient); break; case DeRezAction.Return: this.PerformInventoryReturn(folderID, objectGroups, remoteClient); break; case DeRezAction.GodTakeCopy: this.PerformGodTakeCopy(folderID, objectGroups, remoteClient); break; case DeRezAction.SaveToExistingUserInventoryItem: this.PerformSaveToExistingUserInventoryItem(folderID, objectGroups, remoteClient); break; case DeRezAction.Take: this.PerformTake(folderID, objectGroups, remoteClient, true); break; case DeRezAction.TakeCopy: this.PerformTake(folderID, objectGroups, remoteClient, false); break; } return UUID.Zero; }
/// <summary> /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object /// item. If there are multiple objects then these will be saved as a single coalesced item. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objlist"></param> /// <param name="remoteClient"></param> /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents /// attempted serialization of any script state which would abort any operating scripts.</param> /// <returns>The inventory item created by the copy</returns> protected InventoryItemBase CopyBundleToInventory( DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, bool asAttachment) { CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); // Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); foreach (SceneObjectGroup objectGroup in objlist) { if (objectGroup.RootPart.KeyframeMotion != null) objectGroup.RootPart.KeyframeMotion.Stop(); objectGroup.RootPart.KeyframeMotion = null; // Vector3 inventoryStoredPosition = new Vector3 // (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) // ? 250 // : objectGroup.AbsolutePosition.X) // , // (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) // ? 250 // : objectGroup.AbsolutePosition.Y, // objectGroup.AbsolutePosition.Z); // // originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; // // objectGroup.AbsolutePosition = inventoryStoredPosition; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. objectGroup.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify | (uint)PermissionMask.Export); objectGroup.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; coa.Add(objectGroup); } string itemXml; // If we're being called from a script, then trying to serialize that same script's state will not complete // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if // the client/server crashes rather than logging out normally, the attachment's scripts will resume // without state on relog. Arguably, this is what we want anyway. if (objlist.Count > 1) itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); else itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); // // Restore the position of each group now that it has been stored to inventory. // foreach (SceneObjectGroup objectGroup in objlist) // objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Created item is {0}", // item != null ? item.ID.ToString() : "NULL"); if (item == null) return null; // Can't know creator is the same, so null it in inventory if (objlist.Count > 1) { item.CreatorId = UUID.Zero.ToString(); item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; } else { item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); item.CreatorData = objlist[0].RootPart.CreatorData; item.SaleType = objlist[0].RootPart.ObjectSaleType; item.SalePrice = objlist[0].RootPart.SalePrice; } AssetBase asset = CreateAsset( objlist[0].GetPartName(objlist[0].RootPart.LocalId), objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(itemXml), objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); item.AssetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_Scene.InventoryService.UpdateItem(item); } else { AddPermissions(item, objlist[0], objlist, remoteClient); item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_Scene.AddInventoryItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } // This is a hook to do some per-asset post-processing for subclasses that need that if (remoteClient != null) ExportAsset(remoteClient.AgentId, asset.FullID); return item; }
/// <summary> /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object /// item. If there are multiple objects then these will be saved as a single coalesced item. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objlist"></param> /// <param name="remoteClient"></param> /// <param name="asAttachment">Should be true if the bundle is being copied as an attachment. This prevents /// attempted serialization of any script state which would abort any operating scripts.</param> /// <returns>The inventory item created by the copy</returns> protected InventoryItemBase CopyBundleToInventory( DeRezAction action, UUID folderID, List <SceneObjectGroup> objlist, IClientAPI remoteClient, bool asAttachment) { CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); // Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); Dictionary <SceneObjectGroup, KeyframeMotion> group2Keyframe = new Dictionary <SceneObjectGroup, KeyframeMotion>(); foreach (SceneObjectGroup objectGroup in objlist) { if (objectGroup.RootPart.KeyframeMotion != null) { objectGroup.RootPart.KeyframeMotion.Pause(); group2Keyframe.Add(objectGroup, objectGroup.RootPart.KeyframeMotion); objectGroup.RootPart.KeyframeMotion = null; } // Vector3 inventoryStoredPosition = new Vector3 // (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) // ? 250 // : objectGroup.AbsolutePosition.X) // , // (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) // ? 250 // : objectGroup.AbsolutePosition.Y, // objectGroup.AbsolutePosition.Z); // // originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; // // objectGroup.AbsolutePosition = inventoryStoredPosition; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. objectGroup.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify | (uint)PermissionMask.Export); objectGroup.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; coa.Add(objectGroup); } string itemXml; // If we're being called from a script, then trying to serialize that same script's state will not complete // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if // the client/server crashes rather than logging out normally, the attachment's scripts will resume // without state on relog. Arguably, this is what we want anyway. if (objlist.Count > 1) { itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); } else { itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); } // // Restore the position of each group now that it has been stored to inventory. // foreach (SceneObjectGroup objectGroup in objlist) // objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Created item is {0}", // item != null ? item.ID.ToString() : "NULL"); if (item == null) { return(null); } item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); item.CreatorData = objlist[0].RootPart.CreatorData; if (objlist.Count > 1) { item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; // If the objects have different creators then don't specify a creator at all foreach (SceneObjectGroup objectGroup in objlist) { if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId) || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData)) { item.CreatorId = UUID.Zero.ToString(); item.CreatorData = string.Empty; break; } } } else { item.SaleType = objlist[0].RootPart.ObjectSaleType; item.SalePrice = objlist[0].RootPart.SalePrice; } AssetBase asset = CreateAsset( objlist[0].GetPartName(objlist[0].RootPart.LocalId), objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(itemXml), objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); item.AssetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_Scene.InventoryService.UpdateItem(item); } else { item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; AddPermissions(item, objlist[0], objlist, remoteClient); m_Scene.AddInventoryItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } // Restore KeyframeMotion foreach (SceneObjectGroup objectGroup in group2Keyframe.Keys) { objectGroup.RootPart.KeyframeMotion = group2Keyframe[objectGroup]; objectGroup.RootPart.KeyframeMotion.Start(); } // This is a hook to do some per-asset post-processing for subclasses that need that if (remoteClient != null) { ExportAsset(remoteClient.AgentId, asset.FullID); } return(item); }
/// <summary> /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object /// item. If there are multiple objects then these will be saved as a single coalesced item. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objlist"></param> /// <param name="remoteClient"></param> /// <returns></returns> protected UUID CopyBundleToInventory( DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient) { UUID assetID = UUID.Zero; CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); foreach (SceneObjectGroup objectGroup in objlist) { Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.Y, objectGroup.AbsolutePosition.Z); originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. objectGroup.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify); objectGroup.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; coa.Add(objectGroup); } string itemXml; if (objlist.Count > 1) itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); else itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); // Restore the position of each group now that it has been stored to inventory. foreach (SceneObjectGroup objectGroup in objlist) objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); if (item == null) return UUID.Zero; // Can't know creator is the same, so null it in inventory if (objlist.Count > 1) { item.CreatorId = UUID.Zero.ToString(); item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; } else { item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); item.SaleType = objlist[0].RootPart.ObjectSaleType; item.SalePrice = objlist[0].RootPart.SalePrice; } AssetBase asset = CreateAsset( objlist[0].GetPartName(objlist[0].RootPart.LocalId), objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(itemXml), objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); item.AssetID = asset.FullID; assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_Scene.InventoryService.UpdateItem(item); } else { AddPermissions(item, objlist[0], objlist, remoteClient); item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_Scene.AddInventoryItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } // This is a hook to do some per-asset post-processing for subclasses that need that ExportAsset(remoteClient.AgentId, assetID); return assetID; }
/// <summary> /// Derez one or more objects from the scene. /// </summary> /// <remarks> /// Won't actually remove the scene object in the case where the object is being copied to a user inventory. /// </remarks> /// <param name='remoteClient'>Client requesting derez</param> /// <param name='localIDs'>Local ids of root parts of objects to delete.</param> /// <param name='groupID'>Not currently used. Here because the client passes this to us.</param> /// <param name='action'>DeRezAction</param> /// <param name='destinationID'>User folder ID to place derezzed object</param> public virtual void DeRezObjects( IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) { // First, see of we can perform the requested action and // build a list of eligible objects List<uint> deleteIDs = new List<uint>(); List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection bool permissionToTake = true; bool permissionToTakeCopy = true; bool permissionToDelete = true; foreach (uint localID in localIDs) { // Invalid id SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) continue; // Already deleted by someone else if (part.ParentGroup.IsDeleted) continue; // Can't delete child prims if (part != part.ParentGroup.RootPart) continue; SceneObjectGroup grp = part.ParentGroup; deleteIDs.Add(localID); deleteGroups.Add(grp); // If child prims have invalid perms, fix them grp.AdjustChildPrimPermissions(false); if (remoteClient == null) { // Autoreturn has a null client. Nothing else does. So // allow only returns if (action != DeRezAction.Return) { m_log.WarnFormat( "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client", action, grp.Name, grp.UUID); return; } permissionToTakeCopy = false; } else { if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) permissionToTakeCopy = false; if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) permissionToTake = false; if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) permissionToDelete = false; } } // Handle god perms if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; permissionToDelete = true; } // If we're re-saving, we don't even want to delete if (action == DeRezAction.SaveToExistingUserInventoryItem) permissionToDelete = false; // if we want to take a copy, we also don't want to delete // Note: after this point, the permissionToTakeCopy flag // becomes irrelevant. It already includes the permissionToTake // permission and after excluding no copy items here, we can // just use that. if (action == DeRezAction.TakeCopy) { // If we don't have permission, stop right here if (!permissionToTakeCopy) { remoteClient.SendAlertMessage("You don't have permission to take the object"); return; } permissionToTake = true; // Don't delete permissionToDelete = false; } if (action == DeRezAction.Return) { if (remoteClient != null) { if (Permissions.CanReturnObjects( null, remoteClient.AgentId, deleteGroups)) { permissionToTake = true; permissionToDelete = true; foreach (SceneObjectGroup g in deleteGroups) { AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); } } } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } } if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) { m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, deleteGroups, remoteClient, permissionToDelete); } else if (permissionToDelete) { foreach (SceneObjectGroup g in deleteGroups) DeleteSceneObject(g, false); } }
/// <summary> /// Delete the given object from the scene /// </summary> public void DeleteToInventory(DeRezAction action, UUID folderID, List<ISceneEntity> objectGroups, UUID AgentId, bool permissionToDelete, bool permissionToTake) { DeleteToInventoryHolder dtis = new DeleteToInventoryHolder { action = action, folderID = folderID, objectGroups = objectGroups, agentId = AgentId, permissionToDelete = permissionToDelete, permissionToTake = permissionToTake }; //Do this before the locking so that the objects 'appear' gone and the client doesn't think things have gone wrong if (permissionToDelete) { DeleteGroups(objectGroups); } lock (m_removeFromSimQueue) { m_removeFromSimQueue.Enqueue(dtis); } if (!DeleteLoopInUse) { DeleteLoopInUse = true; //MainConsole.Instance.Debug("[SCENE]: Starting delete loop"); Util.FireAndForget(DoDeleteObject); } }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List <ISceneEntity> objectGroups, UUID agentId, out UUID itemID) { itemID = UUID.Zero; if (objectGroups.Count == 0) { return(UUID.Zero); } UUID assetID = UUID.Zero; Vector3 GroupMiddle = Vector3.Zero; string AssetXML = "<groups>"; if (objectGroups.Count == 1) { m_scene.AuroraEventManager.FireGenericEventHandler("DeleteToInventory", objectGroups[0]); AssetXML = ((ISceneObject)objectGroups[0]).ToXml2(); } else { foreach (ISceneEntity objectGroup in objectGroups) { Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX) ? m_scene.RegionInfo.RegionSizeX - 1 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY) ? m_scene.RegionInfo.RegionSizeY - 1 : objectGroup.AbsolutePosition.Y, objectGroup.AbsolutePosition.Z); GroupMiddle += inventoryStoredPosition; Vector3 originalPosition = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; m_scene.AuroraEventManager.FireGenericEventHandler("DeleteToInventory", objectGroup); AssetXML += ((ISceneObject)objectGroup).ToXml2(); objectGroup.AbsolutePosition = originalPosition; } GroupMiddle.X /= objectGroups.Count; GroupMiddle.Y /= objectGroups.Count; GroupMiddle.Z /= objectGroups.Count; AssetXML += "<middle>"; AssetXML += "<mid>" + GroupMiddle.ToRawString() + "</mid>"; AssetXML += "</middle>"; AssetXML += "</groups>"; } // Get the user info of the item destination // IScenePresence SP = m_scene.GetScenePresence(agentId); UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (SP == null || SP.ControllingClient == null) { return(UUID.Zero); } userID = agentId; } else { // All returns / deletes go to the object owner // userID = objectGroups[0].OwnerID; } if (userID == UUID.Zero) // Can't proceed { return(UUID.Zero); } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(objectGroups[0].RootChild.FromUserInventoryItemID, userID); item = m_scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroups[0].Name, objectGroups[0].UUID); return(UUID.Zero); } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory // if (action == DeRezAction.Attachment || action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory) { if (objectGroups[0].RootChild.FromUserInventoryItemID != UUID.Zero) { InventoryFolderBase f = new InventoryFolderBase(objectGroups[0].RootChild.FromUserInventoryItemID, userID); folder = m_scene.InventoryService.GetFolder(f); } else { folder = m_scene.InventoryService.GetFolderForType(userID, AssetType.Object); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return(UUID.Zero); } } item = new InventoryItemBase(); item.CreatorId = objectGroups[0].RootChild.CreatorID.ToString(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } AssetBase asset = CreateAsset( objectGroups[0].Name, objectGroups[0].RootChild.Description, (sbyte)AssetType.Object, Utils.StringToBytes(AssetXML), objectGroups[0].OwnerID.ToString()); m_scene.AssetService.Store(asset); assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item.AssetID = asset.FullID; m_scene.InventoryService.UpdateItem(item); } else { item.AssetID = asset.FullID; if (SP != null && SP.ControllingClient != null && (SP.ControllingClient.AgentId != objectGroups[0].OwnerID) && m_scene.Permissions.PropagatePermissions()) { foreach (SceneObjectGroup group in objectGroups) { uint perms = group.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint)PermissionMask.Copy) == 0) { perms &= ~(uint)PermissionMask.Copy; } if ((nextPerms & (uint)PermissionMask.Transfer) == 0) { perms &= ~(uint)PermissionMask.Transfer; } if ((nextPerms & (uint)PermissionMask.Modify) == 0) { perms &= ~(uint)PermissionMask.Modify; } // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. group.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify); group.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; item.BasePermissions = perms & group.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = group.RootPart.NextOwnerMask; item.EveryOnePermissions = group.RootPart.EveryoneMask & group.RootPart.NextOwnerMask; item.GroupPermissions = group.RootPart.GroupMask & group.RootPart.NextOwnerMask; // Magic number badness. Maybe this deserves an enum. // bit 4 (16) is the "Slam" bit, it means treat as passed // and apply next owner perms on rez item.CurrentPermissions |= 16; // Slam! } } else { foreach (SceneObjectGroup group in objectGroups) { item.BasePermissions = group.GetEffectivePermissions(); item.CurrentPermissions = group.GetEffectivePermissions(); item.NextPermissions = group.RootPart.NextOwnerMask; item.EveryOnePermissions = group.RootPart.EveryoneMask; item.GroupPermissions = group.RootPart.GroupMask; item.CurrentPermissions &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify | (uint)PermissionMask.Move | 7); // Preserve folded permissions } } // TODO: add the new fields (Flags, Sale info, etc) if (objectGroups.Count != 1) { item.Flags |= (uint)OpenMetaverse.InventoryItemFlags.ObjectHasMultipleItems; } item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_LLCLientInventoryModule.AddInventoryItem(item); if (SP != null && SP.ControllingClient != null && item.Owner == SP.ControllingClient.AgentId) { SP.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } else { IScenePresence notifyUser = m_scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } if (item != null) { itemID = item.ID; } return(assetID); }
public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = UUID.Zero; Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X, objectGroup.AbsolutePosition.Z); Vector3 originalPosition = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); objectGroup.AbsolutePosition = originalPosition; // Get the user info of the item destination // UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (remoteClient == null) { return(UUID.Zero); } userID = remoteClient.AgentId; } else { // All returns / deletes go to the object owner // userID = objectGroup.RootPart.OwnerID; } if (userID == UUID.Zero) // Can't proceed { return(UUID.Zero); } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID); item = m_Scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroup.Name, objectGroup.UUID); return(UUID.Zero); } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (remoteClient == null || objectGroup.OwnerID != remoteClient.AgentId) { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { // Catch all. Use lost & found // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return(UUID.Zero); } } item = new InventoryItemBase(); item.CreatorId = objectGroup.RootPart.CreatorID.ToString(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } AssetBase asset = CreateAsset( objectGroup.GetPartName(objectGroup.RootPart.LocalId), objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(sceneObjectXml), objectGroup.OwnerID.ToString()); m_Scene.AssetService.Store(asset); assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item.AssetID = asset.FullID; m_Scene.InventoryService.UpdateItem(item); } else { item.AssetID = asset.FullID; if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) { uint perms = objectGroup.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint)PermissionMask.Copy) == 0) { perms &= ~(uint)PermissionMask.Copy; } if ((nextPerms & (uint)PermissionMask.Transfer) == 0) { perms &= ~(uint)PermissionMask.Transfer; } if ((nextPerms & (uint)PermissionMask.Modify) == 0) { perms &= ~(uint)PermissionMask.Modify; } item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions |= 8; // Slam! } else { item.BasePermissions = objectGroup.GetEffectivePermissions(); item.CurrentPermissions = objectGroup.GetEffectivePermissions(); item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; item.GroupPermissions = objectGroup.RootPart.GroupMask; item.CurrentPermissions |= 8; // Slam! } // TODO: add the new fields (Flags, Sale info, etc) item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_Scene.InventoryService.AddItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } return(assetID); }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, UUID agentId, out UUID itemID) { itemID = UUID.Zero; if (objectGroups.Count == 0) return UUID.Zero; UUID assetID = UUID.Zero; Vector3 GroupMiddle = Vector3.Zero; string AssetXML = "<groups>"; if (objectGroups.Count == 1) { AssetXML = SceneObjectSerializer.ToOriginalXmlFormat(objectGroups[0]); } else { foreach (SceneObjectGroup objectGroup in objectGroups) { Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.Y, objectGroup.AbsolutePosition.Z); GroupMiddle += inventoryStoredPosition; Vector3 originalPosition = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; AssetXML += SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); objectGroup.AbsolutePosition = originalPosition; } GroupMiddle.X /= objectGroups.Count; GroupMiddle.Y /= objectGroups.Count; GroupMiddle.Z /= objectGroups.Count; AssetXML += "<middle>"; AssetXML += "<mid>" + GroupMiddle.ToRawString() + "</mid>"; AssetXML += "</middle>"; AssetXML += "</groups>"; } // Get the user info of the item destination // ScenePresence SP = m_Scene.GetScenePresence(agentId); UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (SP == null || SP.ControllingClient == null) return UUID.Zero; userID = agentId; } else { // All returns / deletes go to the object owner // userID = objectGroups[0].RootPart.OwnerID; } if (userID == UUID.Zero) // Can't proceed { return UUID.Zero; } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(objectGroups[0].RootPart.FromUserInventoryItemID, userID); item = m_Scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroups[0].Name, objectGroups[0].UUID); return UUID.Zero; } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory // if (action == DeRezAction.Attachment || action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory) { if (objectGroups[0].RootPart.FromItemID != UUID.Zero) { InventoryFolderBase f = new InventoryFolderBase(objectGroups[0].RootPart.FromItemID, userID); folder = m_Scene.InventoryService.GetFolder(f); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return UUID.Zero; } } item = new InventoryItemBase(); item.CreatorId = objectGroups[0].RootPart.CreatorID.ToString(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } AssetBase asset = CreateAsset( objectGroups[0].GetPartName(objectGroups[0].RootPart.LocalId), objectGroups[0].GetPartDescription(objectGroups[0].RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(AssetXML), objectGroups[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item.AssetID = asset.FullID; m_Scene.InventoryService.UpdateItem(item); } else { item.AssetID = asset.FullID; if (SP != null && SP.ControllingClient != null && (SP.ControllingClient.AgentId != objectGroups[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectGroup group in objectGroups) { uint perms = group.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint)PermissionMask.Copy) == 0) perms &= ~(uint)PermissionMask.Copy; if ((nextPerms & (uint)PermissionMask.Transfer) == 0) perms &= ~(uint)PermissionMask.Transfer; if ((nextPerms & (uint)PermissionMask.Modify) == 0) perms &= ~(uint)PermissionMask.Modify; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. group.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify); group.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; item.BasePermissions = perms & group.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = group.RootPart.NextOwnerMask; item.EveryOnePermissions = group.RootPart.EveryoneMask & group.RootPart.NextOwnerMask; item.GroupPermissions = group.RootPart.GroupMask & group.RootPart.NextOwnerMask; // Magic number badness. Maybe this deserves an enum. // bit 4 (16) is the "Slam" bit, it means treat as passed // and apply next owner perms on rez item.CurrentPermissions |= 16; // Slam! } } else { foreach (SceneObjectGroup group in objectGroups) { item.BasePermissions = group.GetEffectivePermissions(); item.CurrentPermissions = group.GetEffectivePermissions(); item.NextPermissions = group.RootPart.NextOwnerMask; item.EveryOnePermissions = group.RootPart.EveryoneMask; item.GroupPermissions = group.RootPart.GroupMask; item.CurrentPermissions &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify | (uint)PermissionMask.Move | 7); // Preserve folded permissions } } // TODO: add the new fields (Flags, Sale info, etc) if(objectGroups.Count != 1) item.Flags |= (uint)OpenMetaverse.InventoryItemFlags.ObjectHasMultipleItems; item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_LLCLientInventoryModule.AddInventoryItem(item); if (SP != null && SP.ControllingClient != null && item.Owner == SP.ControllingClient.AgentId) { SP.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } if (item != null) itemID = item.ID; return assetID; }
public virtual void DeRezObject(IClientAPI remoteClient, uint localId, UUID groupId, DeRezAction action, UUID destinationID) { List<uint> partInfo = new List<uint>(); partInfo.Add(localId); this.DeRezObjects(remoteClient, partInfo, groupId, action, destinationID); }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = UUID.Zero; Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X, objectGroup.AbsolutePosition.Z); Vector3 originalPosition = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); objectGroup.AbsolutePosition = originalPosition; // Get the user info of the item destination // UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (remoteClient == null) return UUID.Zero; userID = remoteClient.AgentId; } else { // All returns / deletes go to the object owner // userID = objectGroup.RootPart.OwnerID; } if (userID == UUID.Zero) // Can't proceed { return UUID.Zero; } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID); item = m_Scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroup.Name, objectGroup.UUID); return UUID.Zero; } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (remoteClient == null || objectGroup.OwnerID != remoteClient.AgentId) { // Folder skeleton may not be loaded and we // have to wait for the inventory to find // the destination folder // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { // Assume inventory skeleton was loaded during login // and all folders can be found // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { // Catch all. Use lost & found // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } } if (folder == null) // None of the above { //folder = userInfo.RootFolder.FindFolder(folderID); folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return UUID.Zero; } } item = new InventoryItemBase(); item.CreatorId = objectGroup.RootPart.CreatorID.ToString(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } AssetBase asset = CreateAsset( objectGroup.GetPartName(objectGroup.RootPart.LocalId), objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(sceneObjectXml), objectGroup.OwnerID.ToString()); m_Scene.AssetService.Store(asset); assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item.AssetID = asset.FullID; m_Scene.InventoryService.UpdateItem(item); } else { item.AssetID = asset.FullID; if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) { uint perms = objectGroup.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint)PermissionMask.Copy) == 0) perms &= ~(uint)PermissionMask.Copy; if ((nextPerms & (uint)PermissionMask.Transfer) == 0) perms &= ~(uint)PermissionMask.Transfer; if ((nextPerms & (uint)PermissionMask.Modify) == 0) perms &= ~(uint)PermissionMask.Modify; item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions |= 8; // Slam! } else { item.BasePermissions = objectGroup.GetEffectivePermissions(); item.CurrentPermissions = objectGroup.GetEffectivePermissions(); item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; item.GroupPermissions = objectGroup.RootPart.GroupMask; item.CurrentPermissions |= 8; // Slam! } // TODO: add the new fields (Flags, Sale info, etc) item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_Scene.InventoryService.AddItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } return assetID; }
/// <summary> /// Called when an object is removed from the environment into inventory. /// </summary> /// <param name="remoteClient"></param> /// <param name="localID"></param> /// <param name="groupID"></param> /// <param name="action"></param> /// <param name="destinationID"></param> public virtual void DeRezObjects(IClientAPI remoteClient, ICollection<uint> objectParts, UUID groupId, DeRezAction action, UUID destinationID) { //get the intended behavior of this action DeRezActionResult intendedResult = this.GetIntendedResult(action); //List for collecting found prims List<SceneObjectGroup> groupsToDerez = new List<SceneObjectGroup>(); bool abort = false; bool reportErrorForNoGroupsReturned = true; using (SceneTransaction transaction = SceneGraph.BeginPrimTransaction(objectParts)) { try { //check to make sure each part can meet the intended result //skip with null client if (remoteClient != null) { foreach (uint partInfo in objectParts) { SceneObjectGroup grp = this.FindGroupAppropriateForDeRez(partInfo); if (grp == null) return; //couldn't find groups if (grp.IsAttachment) continue; //none of this should be done on attachments if (this.FindDeRezPermissions(remoteClient, grp, action) != this.GetIntendedResult(action)) { //missing permissions for one or more of the objects remoteClient.SendAlertMessage("Insuffient permissions on '" + grp.Name + "'."); return; } else { if (!this.AddToListIfDerezOk(intendedResult, grp, groupsToDerez)) { //could not derez abort = true; remoteClient.SendBlueBoxMessage(UUID.Zero, String.Empty, "Could not take/remove '" + grp.Name + "', operation aborted."); return; } } } } else { //delete called from parcel return foreach (uint partInfo in objectParts) { SceneObjectGroup grp = this.FindGroupAppropriateForDeRez(partInfo); if (grp == null) return; //couldn't find groups if (grp.IsAttachment) continue; //none of this should be done on attachments //protect against a return on the same object happing multiple times if (!this.AddToListIfDerezOk(intendedResult, grp, groupsToDerez)) { //could not derez reportErrorForNoGroupsReturned = false; continue; } } } if (groupsToDerez.Count == 0) { //there must've been a problem locating the group(s), inform the user if (reportErrorForNoGroupsReturned) { m_log.ErrorFormat("[Scene.Inventory] No groups found to derez after scene search, Action: {0}", action); } /* if (remoteClient != null) { remoteClient.SendBlueBoxMessage(UUID.Zero, String.Empty, "Could not find objects to derez"); } */ return; } //if we got here, we can start completing the requested action ForceBulkSceneObjectBackup(groupsToDerez); if (intendedResult == DeRezActionResult.Both || intendedResult == DeRezActionResult.Take) { m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, groupsToDerez, remoteClient, intendedResult == DeRezActionResult.Both //also delete? ); } else if (intendedResult == DeRezActionResult.Delete) { DeleteSceneObjects(groupsToDerez, false); } } finally { if (abort) { //clean up the derezzed flag foreach (var group in groupsToDerez) { group.IsBeingDerezzed = false; } } } } }
/// /// DeleteToInventory /// public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient); if (!assetID.Equals(UUID.Zero)) { UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); } else m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); return assetID; }
public virtual List<InventoryItemBase> CopyToInventory( DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, bool asAttachment) { List<InventoryItemBase> copiedItems = new List<InventoryItemBase>(); Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); if (CoalesceMultipleObjectsToInventory) { // The following code groups the SOG's by owner. No objects // belonging to different people can be coalesced, for obvious // reasons. foreach (SceneObjectGroup g in objectGroups) { if (!bundlesToCopy.ContainsKey(g.OwnerID)) bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>(); bundlesToCopy[g.OwnerID].Add(g); } } else { // If we don't want to coalesce then put every object in its own bundle. foreach (SceneObjectGroup g in objectGroups) { List<SceneObjectGroup> bundle = new List<SceneObjectGroup>(); bundle.Add(g); bundlesToCopy[g.UUID] = bundle; } } // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}", // bundlesToCopy.Count, folderID, action, remoteClient.Name); // Each iteration is really a separate asset being created, // with distinct destinations as well. foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); return copiedItems; }
/// <summary> /// Called when one or more objects are removed from the environment into inventory. /// </summary> /// <param name="remoteClient"></param> /// <param name="localID"></param> /// <param name="groupID"></param> /// <param name="action"></param> /// <param name="destinationID"></param> public virtual void DeRezObject(IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) { foreach (uint localID in localIDs) { DeRezObject(remoteClient, localID, groupID, action, destinationID); } }
/// <summary> /// Create an item using details for the given scene object. /// </summary> /// <param name="action"></param> /// <param name="remoteClient"></param> /// <param name="so"></param> /// <param name="folderID"></param> /// <returns></returns> protected InventoryItemBase CreateItemForObject( DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) { // Get the user info of the item destination // UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (remoteClient == null) return null; userID = remoteClient.AgentId; // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is {1} {2}", // action, remoteClient.Name, userID); } else if (so.RootPart.OwnerID == so.RootPart.GroupID) { // Group owned objects go to the last owner before the object was transferred. userID = so.RootPart.LastOwnerID; } else { // Other returns / deletes go to the object owner // userID = so.RootPart.OwnerID; // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Target of {0} in CreateItemForObject() is object owner {1}", // action, userID); } if (userID == UUID.Zero) // Can't proceed { return null; } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); item = m_Scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", so.Name, so.UUID); return null; } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (remoteClient == null || so.OwnerID != remoteClient.AgentId) { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId) { // Taking copy of another person's item. Take to // Objects folder. folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); so.FromFolderID = UUID.Zero; } else { // Catch all. Use lost & found // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory and the owner is taking it back. // if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) { if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) { InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); folder = m_Scene.InventoryService.GetFolder(f); if(folder.Type == 14 || folder.Type == 16) { // folder.Type = 6; folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); } } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return null; } } item = new InventoryItemBase(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } return item; }
/// <summary> /// Called when an object is removed from the environment into inventory. /// </summary> /// <param name="remoteClient"></param> /// <param name="localID"></param> /// <param name="groupID"></param> /// <param name="action"></param> /// <param name="destinationID"></param> public virtual void DeRezObject(IClientAPI remoteClient, uint localID, UUID groupID, DeRezAction action, UUID destinationID) { SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) return; if (part.ParentGroup == null || part.ParentGroup.IsDeleted) return; // Can't delete child prims if (part != part.ParentGroup.RootPart) return; SceneObjectGroup grp = part.ParentGroup; //force a database backup/update on this SceneObjectGroup //So that we know the database is upto date, for when deleting the object from it ForceSceneObjectBackup(grp); bool permissionToTake = false; bool permissionToDelete = false; if (action == DeRezAction.SaveToExistingUserInventoryItem) { if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) { permissionToTake = true; permissionToDelete = false; } } else if (action == DeRezAction.TakeCopy) { permissionToTake = Permissions.CanTakeCopyObject( grp.UUID, remoteClient.AgentId); } else if (action == DeRezAction.GodTakeCopy) { permissionToTake = Permissions.IsGod( remoteClient.AgentId); } else if (action == DeRezAction.Take) { permissionToTake = Permissions.CanTakeObject( grp.UUID, remoteClient.AgentId); //If they can take, they can delete! permissionToDelete = permissionToTake; } else if (action == DeRezAction.Delete) { permissionToTake = Permissions.CanDeleteObject( grp.UUID, remoteClient.AgentId); permissionToDelete = permissionToTake; } else if (action == DeRezAction.Return) { if (remoteClient != null) { permissionToTake = Permissions.CanReturnObject( grp.UUID, remoteClient.AgentId); permissionToDelete = permissionToTake; if (permissionToDelete) { AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); } } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } } else { m_log.DebugFormat( "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name); return; } if (permissionToTake) { m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, grp, remoteClient, permissionToDelete); } else if (permissionToDelete) { DeleteSceneObject(grp, false); } }
public virtual void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) { // First, see of we can perform the requested action and // build a list of eligible objects List<uint> deleteIDs = new List<uint>(); List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection bool permissionToTake = true; bool permissionToTakeCopy = true; bool permissionToDelete = true; foreach (uint localID in localIDs) { // Invalid id SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) continue; // Already deleted by someone else if (part.ParentGroup == null || part.ParentGroup.IsDeleted) continue; // Can't delete child prims if (part != part.ParentGroup.RootPart) continue; SceneObjectGroup grp = part.ParentGroup; deleteIDs.Add(localID); deleteGroups.Add(grp); // Force a database backup/update on this SceneObjectGroup // So that we know the database is upto date, // for when deleting the object from it ForceSceneObjectBackup(grp); if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) permissionToTakeCopy = false; if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) permissionToTake = false; if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) permissionToDelete = false; } // Handle god perms if (Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; permissionToDelete = true; } // If we're re-saving, we don't even want to delete if (action == DeRezAction.SaveToExistingUserInventoryItem) permissionToDelete = false; // if we want to take a copy,, we also don't want to delete // Note: after this point, the permissionToTakeCopy flag // becomes irrelevant. It already includes the permissionToTake // permission and after excluding no copy items here, we can // just use that. if (action == DeRezAction.TakeCopy) { // If we don't have permission, stop right here if (!permissionToTakeCopy) return; // Don't delete permissionToDelete = false; } if (action == DeRezAction.Return) { if (remoteClient != null) { if (Permissions.CanReturnObjects( null, remoteClient.AgentId, deleteGroups)) { permissionToTake = true; permissionToDelete = true; foreach (SceneObjectGroup g in deleteGroups) { AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); } } } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } } if (permissionToTake) { m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, deleteGroups, remoteClient, permissionToDelete); } else if (permissionToDelete) { foreach (SceneObjectGroup g in deleteGroups) DeleteSceneObject(g, false); } }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroups"></param> /// <param name="agentId"></param> /// <param name="itemID"></param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List<ISceneEntity> objectGroups, UUID agentId, out UUID itemID) { itemID = UUID.Zero; if (objectGroups.Count == 0) return UUID.Zero; // Get the user info of the item destination // IScenePresence SP = m_scene.GetScenePresence(agentId); UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (SP == null || SP.ControllingClient == null) return UUID.Zero; userID = agentId; } else { // All returns / deletes go to the object owner // userID = objectGroups[0].OwnerID; } if (userID == UUID.Zero) // Can't proceed { return UUID.Zero; } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = m_scene.InventoryService.GetItem(userID, objectGroups[0].RootChild.FromUserInventoryItemID); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { MainConsole.Instance.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", objectGroups[0].Name, objectGroups[0].UUID); return UUID.Zero; } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } else { if (SP == null || SP.ControllingClient == null || objectGroups[0].OwnerID != agentId) { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.LostAndFoundFolder); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown, AssetType.TrashFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory // if (action == DeRezAction.Attachment || action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory) { if (objectGroups[0].RootChild.FromUserInventoryItemID != UUID.Zero) { InventoryFolderBase f = new InventoryFolderBase(objectGroups[0].RootChild.FromUserInventoryItemID, userID); folder = m_scene.InventoryService.GetFolder(f); } else { folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Object, AssetType.Object); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); } item = new InventoryItemBase { CreatorId = objectGroups[0].RootChild.CreatorID.ToString(), ID = UUID.Random(), InvType = (int) InventoryType.Object, Folder = folder.ID, Owner = userID }; } AssetBase asset; UUID assetID = SaveAsAsset(objectGroups, out asset); item.AssetID = assetID; if (DeRezAction.SaveToExistingUserInventoryItem != action) { item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; } if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_scene.InventoryService.UpdateItem(item); } else { if (SP != null && SP.ControllingClient != null && (SP.ControllingClient.AgentId != objectGroups[0].OwnerID) && m_scene.Permissions.PropagatePermissions()) { foreach (ISceneEntity group in objectGroups) { uint perms = group.GetEffectivePermissions(); uint nextPerms = (perms & 7) << 13; if ((nextPerms & (uint) PermissionMask.Copy) == 0) perms &= ~(uint) PermissionMask.Copy; if ((nextPerms & (uint) PermissionMask.Transfer) == 0) perms &= ~(uint) PermissionMask.Transfer; if ((nextPerms & (uint) PermissionMask.Modify) == 0) perms &= ~(uint) PermissionMask.Modify; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. group.RootChild.NextOwnerMask &= ((uint) PermissionMask.Copy | (uint) PermissionMask.Transfer | (uint) PermissionMask.Modify); group.RootChild.NextOwnerMask |= (uint) PermissionMask.Move; item.BasePermissions = perms & group.RootChild.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = group.RootChild.NextOwnerMask; item.EveryOnePermissions = group.RootChild.EveryoneMask & group.RootChild.NextOwnerMask; item.GroupPermissions = group.RootChild.GroupMask & group.RootChild.NextOwnerMask; // Magic number badness. Maybe this deserves an enum. // bit 4 (16) is the "Slam" bit, it means treat as passed // and apply next owner perms on rez item.CurrentPermissions |= 16; // Slam! item.SalePrice = group.RootChild.SalePrice; item.SaleType = group.RootChild.ObjectSaleType; } } else { foreach (ISceneEntity group in objectGroups) { item.BasePermissions = group.GetEffectivePermissions(); item.CurrentPermissions = group.GetEffectivePermissions(); item.NextPermissions = group.RootChild.NextOwnerMask; item.EveryOnePermissions = group.RootChild.EveryoneMask; item.GroupPermissions = group.RootChild.GroupMask; item.SalePrice = group.RootChild.SalePrice; item.SaleType = group.RootChild.ObjectSaleType; item.CurrentPermissions &= ((uint) PermissionMask.Copy | (uint) PermissionMask.Transfer | (uint) PermissionMask.Modify | (uint) PermissionMask.Move | 7); // Preserve folded permissions } } if (objectGroups.Count != 1) item.Flags |= (uint) InventoryItemFlags.ObjectHasMultipleItems; item.CreationDate = Util.UnixTimeSinceEpoch(); m_LLCLientInventoryModule.AddInventoryItem(item); if (SP != null && SP.ControllingClient != null && item.Owner == SP.ControllingClient.AgentId) { SP.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } else { IScenePresence notifyUser = m_scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } itemID = item.ID; return assetID; }
/// <summary> /// Delete a scene object from a scene and place in the given avatar's inventory. /// Returns the UUID of the newly created asset. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objectGroup"></param> /// <param name="remoteClient"> </param> public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) { // HACK: This is only working for lists containing a single item! // It's just a hack to make this WIP compile and run. Nothing // currently calls this with multiple items. UUID ret = UUID.Zero; Dictionary<UUID, List<SceneObjectGroup>> deletes = new Dictionary<UUID, List<SceneObjectGroup>>(); foreach (SceneObjectGroup g in objectGroups) { if (!deletes.ContainsKey(g.OwnerID)) deletes[g.OwnerID] = new List<SceneObjectGroup>(); deletes[g.OwnerID].Add(g); } foreach (List<SceneObjectGroup> objlist in deletes.Values) { foreach (SceneObjectGroup g in objlist) ret = DeleteToInventory(action, folderID, g, remoteClient); } return ret; }
public bool TriggerDeRezRequested(IClientAPI client, List<SceneObjectGroup> objs, DeRezAction action) { bool canDeRez = true; DeRezRequested handlerDeRezRequested = OnDeRezRequested; if (handlerDeRezRequested != null) { foreach (DeRezRequested d in handlerDeRezRequested.GetInvocationList()) { try { canDeRez &= d(client, objs, action); } catch (Exception e) { m_log.ErrorFormat( "[EVENT MANAGER]: Delegate for TriggerDeRezRequested failed - continuing. {0} {1}", e.Message, e.StackTrace); } } } return canDeRez; }
/// <summary> /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object /// item. If there are multiple objects then these will be saved as a single coalesced item. /// </summary> /// <param name="action"></param> /// <param name="folderID"></param> /// <param name="objlist"></param> /// <param name="remoteClient"></param> /// <returns></returns> protected UUID CopyBundleToInventory( DeRezAction action, UUID folderID, List <SceneObjectGroup> objlist, IClientAPI remoteClient) { UUID assetID = UUID.Zero; CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); Dictionary <UUID, Vector3> originalPositions = new Dictionary <UUID, Vector3>(); foreach (SceneObjectGroup objectGroup in objlist) { Vector3 inventoryStoredPosition = new Vector3 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.X) , (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) ? 250 : objectGroup.AbsolutePosition.Y, objectGroup.AbsolutePosition.Z); originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; objectGroup.AbsolutePosition = inventoryStoredPosition; // Make sure all bits but the ones we want are clear // on take. // This will be applied to the current perms, so // it will do what we want. objectGroup.RootPart.NextOwnerMask &= ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | (uint)PermissionMask.Modify); objectGroup.RootPart.NextOwnerMask |= (uint)PermissionMask.Move; coa.Add(objectGroup); } string itemXml; if (objlist.Count > 1) { itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); } else { itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); } // Restore the position of each group now that it has been stored to inventory. foreach (SceneObjectGroup objectGroup in objlist) { objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; } InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); if (item == null) { return(UUID.Zero); } // Can't know creator is the same, so null it in inventory if (objlist.Count > 1) { item.CreatorId = UUID.Zero.ToString(); item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; } else { item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); item.SaleType = objlist[0].RootPart.ObjectSaleType; item.SalePrice = objlist[0].RootPart.SalePrice; } AssetBase asset = CreateAsset( objlist[0].GetPartName(objlist[0].RootPart.LocalId), objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), (sbyte)AssetType.Object, Utils.StringToBytes(itemXml), objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); item.AssetID = asset.FullID; assetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { m_Scene.InventoryService.UpdateItem(item); } else { AddPermissions(item, objlist[0], objlist, remoteClient); item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; item.AssetType = asset.Type; m_Scene.AddInventoryItem(item); if (remoteClient != null && item.Owner == remoteClient.AgentId) { remoteClient.SendInventoryItemCreateUpdate(item, 0); } else { ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); if (notifyUser != null) { notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } } } // This is a hook to do some per-asset post-processing for subclasses that need that ExportAsset(remoteClient.AgentId, assetID); return(assetID); }
public virtual void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) { // First, see of we can perform the requested action and // build a list of eligible objects List<uint> deleteIDs = new List<uint>(); List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection bool permissionToTake = true; bool permissionToTakeCopy = true; bool permissionToDelete = true; foreach (uint localID in localIDs) { // Invalid id SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) continue; // Already deleted by someone else if (part.ParentGroup == null || part.ParentGroup.IsDeleted) continue; // Can't delete child prims if (part != part.ParentGroup.RootPart) continue; SceneObjectGroup grp = part.ParentGroup; deleteIDs.Add(localID); deleteGroups.Add(grp); ScenePresence SP = remoteClient == null ? null : GetScenePresence(remoteClient.AgentId); if (SP == null) { // Autoreturn has a null client. Nothing else does. So // allow only returns if (action != DeRezAction.Return) return; permissionToTakeCopy = false; } else { if (!Permissions.CanTakeCopyObject(grp.UUID, SP.UUID)) permissionToTakeCopy = false; if (!Permissions.CanTakeObject(grp.UUID, SP.UUID)) permissionToTake = false; if (!Permissions.CanDeleteObject(grp.UUID, SP.UUID)) permissionToDelete = false; } } // Handle god perms if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; permissionToDelete = true; } // If we're re-saving, we don't even want to delete if (action == DeRezAction.SaveToExistingUserInventoryItem) permissionToDelete = false; // if we want to take a copy, we also don't want to delete // Note: after this point, the permissionToTakeCopy flag // becomes irrelevant. It already includes the permissionToTake // permission and after excluding no copy items here, we can // just use that. if (action == DeRezAction.TakeCopy) { // If we don't have permission, stop right here if (!permissionToTakeCopy) return; permissionToTake = true; // Don't delete permissionToDelete = false; } if (action == DeRezAction.Return) { if (remoteClient != null && Permissions.CanReturnObjects( null, remoteClient.AgentId, deleteGroups)) { permissionToTake = true; permissionToDelete = true; AddReturns(deleteGroups[0].OwnerID, deleteGroups[0].Name, deleteGroups.Count, deleteGroups[0].AbsolutePosition, "parcel owner return", deleteGroups); } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } } //if (permissionToTake) //{ m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, deleteGroups, remoteClient == null ? UUID.Zero : remoteClient.AgentId, permissionToDelete, permissionToTake); //} //else if (permissionToDelete) //{ // foreach (SceneObjectGroup g in deleteGroups) // DeleteSceneObject(g, false, true); //} }
/// <summary> /// Create an item using details for the given scene object. /// </summary> /// <param name="action"></param> /// <param name="remoteClient"></param> /// <param name="so"></param> /// <param name="folderID"></param> /// <returns></returns> protected InventoryItemBase CreateItemForObject( DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) { // Get the user info of the item destination // UUID userID = UUID.Zero; if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || action == DeRezAction.SaveToExistingUserInventoryItem) { // Take or take copy require a taker // Saving changes requires a local user // if (remoteClient == null) { return(null); } userID = remoteClient.AgentId; } else { // All returns / deletes go to the object owner // userID = so.RootPart.OwnerID; } if (userID == UUID.Zero) // Can't proceed { return(null); } // If we're returning someone's item, it goes back to the // owner's Lost And Found folder. // Delete is treated like return in this case // Deleting your own items makes them go to trash // InventoryFolderBase folder = null; InventoryItemBase item = null; if (DeRezAction.SaveToExistingUserInventoryItem == action) { item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); item = m_Scene.InventoryService.GetItem(item); //item = userInfo.RootFolder.FindItem( // objectGroup.RootPart.FromUserInventoryItemID); if (null == item) { m_log.DebugFormat( "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", so.Name, so.UUID); return(null); } } else { // Folder magic // if (action == DeRezAction.Delete) { // Deleting someone else's item // if (remoteClient == null || so.OwnerID != remoteClient.AgentId) { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) { // Dump to lost + found unconditionally // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } if (folderID == UUID.Zero && folder == null) { if (action == DeRezAction.Delete) { // Deletes go to trash by default // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } else { if (remoteClient == null || so.OwnerID != remoteClient.AgentId) { // Taking copy of another person's item. Take to // Objects folder. folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); } else { // Catch all. Use lost & found // folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } } } // Override and put into where it came from, if it came // from anywhere in inventory // if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) { if (so.RootPart.FromFolderID != UUID.Zero) { InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); folder = m_Scene.InventoryService.GetFolder(f); } } if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it { return(null); } } item = new InventoryItemBase(); item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; item.Owner = userID; } return(item); }
/// <summary> /// Delete the given objects from the Scene and move them into the client's inventory /// </summary> /// <param name="remoteClient">The client requesting the change (can be null if returning objects)</param> /// <param name="localIDs">A list of all the localIDs of the groups to delete</param> /// <param name="groupID">the GroupID of the objects</param> /// <param name="action">What type of action is causing this</param> /// <param name="destinationID">The folder ID to put the inventory items in</param> protected void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) { // First, see of we can perform the requested action and // build a list of eligible objects List<uint> deleteIDs = new List<uint>(); List<ISceneEntity> deleteGroups = new List<ISceneEntity> (); #region Permission Check // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection bool permissionToTake = true; bool permissionToTakeCopy = true; bool permissionToDelete = true; foreach (uint localID in localIDs) { // Invalid id ISceneChildEntity part = m_scene.GetSceneObjectPart (localID); if (part == null) continue; // Already deleted by someone else if (part.ParentEntity == null || part.ParentEntity.IsDeleted) continue; // Can't delete child prims if (part != part.ParentEntity.RootChild) continue; ISceneEntity grp = part.ParentEntity; deleteIDs.Add(localID); deleteGroups.Add(grp); IScenePresence SP = remoteClient == null ? null : m_scene.GetScenePresence (remoteClient.AgentId); if (SP == null) { // Autoreturn has a null client. Nothing else does. So // allow only returns if (action != DeRezAction.Return) return; permissionToTakeCopy = false; } else { if (!m_scene.Permissions.CanTakeCopyObject(grp.UUID, SP.UUID)) permissionToTakeCopy = false; if (!m_scene.Permissions.CanTakeObject(grp.UUID, SP.UUID)) permissionToTake = false; if (!m_scene.Permissions.CanDeleteObject(grp.UUID, SP.UUID)) permissionToDelete = false; } } #endregion // Handle god perms if ((remoteClient != null) && m_scene.Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; permissionToDelete = true; } // If we're re-saving, we don't even want to delete if (action == DeRezAction.SaveToExistingUserInventoryItem) permissionToDelete = false; // if we want to take a copy, we also don't want to delete // Note: after this point, the permissionToTakeCopy flag // becomes irrelevant. It already includes the permissionToTake // permission and after excluding no copy items here, we can // just use that. if (action == DeRezAction.AcquireToUserInventory) { // If we don't have permission, stop right here if (!permissionToTakeCopy) return; permissionToTake = true; // Don't delete permissionToDelete = false; } if (action == DeRezAction.Return) { if (remoteClient != null && m_scene.Permissions.CanReturnObjects( null, remoteClient.AgentId, deleteGroups)) { permissionToTake = true; permissionToDelete = true; IParcelManagementModule parcelManagement = m_scene.RequestModuleInterface<IParcelManagementModule>(); if (parcelManagement != null) { parcelManagement.AddReturns(deleteGroups[0].OwnerID, deleteGroups[0].Name, deleteGroups[0].AbsolutePosition, "Parcel Owner Return", deleteGroups); } } else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; } } IAsyncSceneObjectGroupDeleter asyncDelete = m_scene.RequestModuleInterface<IAsyncSceneObjectGroupDeleter>(); if (asyncDelete != null) { asyncDelete.DeleteToInventory( action, destinationID, deleteGroups, remoteClient == null ? UUID.Zero : remoteClient.AgentId, permissionToDelete, permissionToTake); } }
public virtual UUID CopyToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) { Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); if (CoalesceMultipleObjectsToInventory) { // The following code groups the SOG's by owner. No objects // belonging to different people can be coalesced, for obvious // reasons. foreach (SceneObjectGroup g in objectGroups) { if (!bundlesToCopy.ContainsKey(g.OwnerID)) bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>(); bundlesToCopy[g.OwnerID].Add(g); } } else { // If we don't want to coalesce then put every object in its own bundle. foreach (SceneObjectGroup g in objectGroups) { List<SceneObjectGroup> bundle = new List<SceneObjectGroup>(); bundle.Add(g); bundlesToCopy[g.UUID] = bundle; } } // This is method scoped and will be returned. It will be the // last created asset id UUID assetID = UUID.Zero; // Each iteration is really a separate asset being created, // with distinct destinations as well. foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient); return assetID; }