diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 93aeb9440f..2ab46aa33f 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -119,9 +119,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// DeleteToInventory /// - public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) + public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient) { - UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, 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; + } + + public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, + SceneObjectGroup objectGroup, IClientAPI remoteClient) + { + UUID assetID = base.DeleteToInventory(action, folderID, new List() {objectGroup}, remoteClient); if (!assetID.Equals(UUID.Zero)) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 901dcba707..3035d889e7 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -188,6 +188,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// /// + public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, + List 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 UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 81852583c6..97f4188751 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IInventoryAccessModule { UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data); - UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient); + UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient); SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index c08b961373..241cac0f11 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes { public DeRezAction action; public IClientAPI remoteClient; - public SceneObjectGroup objectGroup; + public List objectGroups; public UUID folderID; public bool permissionToDelete; } @@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes /// Delete the given object from the scene /// public void DeleteToInventory(DeRezAction action, UUID folderID, - SceneObjectGroup objectGroup, IClientAPI remoteClient, + List objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; - dtis.objectGroup = objectGroup; + dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; @@ -103,7 +103,10 @@ namespace OpenSim.Region.Framework.Scenes // 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); + { + foreach (SceneObjectGroup g in objectGroups) + g.DeleteGroup(false); + } } private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) @@ -140,9 +143,12 @@ namespace OpenSim.Region.Framework.Scenes { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) - invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); + invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); if (x.permissionToDelete) - m_scene.DeleteSceneObject(x.objectGroup, false); + { + foreach (SceneObjectGroup g in x.objectGroups) + m_scene.DeleteSceneObject(g, false); + } } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cbe34568e9..e1128a6e75 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1550,79 +1550,98 @@ namespace OpenSim.Region.Framework.Scenes public virtual void DeRezObject(IClientAPI remoteClient, uint localID, UUID groupID, DeRezAction action, UUID destinationID) { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part == null) - return; + DeRezObjects(remoteClient, new List() { localID} , groupID, action, destinationID); + } - if (part.ParentGroup == null || part.ParentGroup.IsDeleted) - return; + public virtual void DeRezObjects(IClientAPI remoteClient, List localIDs, + UUID groupID, DeRezAction action, UUID destinationID) + { + // First, see of we can perform the requested action and + // build a list of eligible objects + List deleteIDs = new List(); + List deleteGroups = new List(); - // Can't delete child prims - if (part != part.ParentGroup.RootPart) - return; + // 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; - 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) + foreach (uint localID in localIDs) { - if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) - { - permissionToTake = true; + // 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; - } - } - 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) + + // Handle god perms + if (Permissions.IsGod(remoteClient.AgentId)) { - permissionToTake = - Permissions.CanDeleteObject( - grp.UUID, - remoteClient.AgentId); - permissionToDelete = permissionToTake; + permissionToTake = true; + permissionToTakeCopy = true; + permissionToDelete = true; } - else if (action == DeRezAction.Return) + + // 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) { - permissionToTake = - Permissions.CanReturnObjects( + if (Permissions.CanReturnObjects( null, remoteClient.AgentId, - new List() {grp}); - permissionToDelete = permissionToTake; - - if (permissionToDelete) + deleteGroups)) + foreach (SceneObjectGroup g in deleteGroups) { - AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); + AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); + DeleteSceneObject(g, false); + return; } } else // Auto return passes through here with null agent @@ -1631,22 +1650,17 @@ namespace OpenSim.Region.Framework.Scenes 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, + action, destinationID, deleteGroups, remoteClient, permissionToDelete); } else if (permissionToDelete) { - DeleteSceneObject(grp, false); + foreach (SceneObjectGroup g in deleteGroups) + DeleteSceneObject(g, false); } }