/// <summary> /// Store the asset for the given item when it has been uploaded. /// </summary> /// <param name="item"></param> private bool CompleteItemUpdate(InventoryItemBase item) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // m_asset.FullID, item.Name, ourClient.Name); uint perms = ValidateAssets(); if (perms == 0) { string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', update failed", item.Name); ourClient.SendAlertMessage(error); m_transactions.RemoveXferUploader(m_transactionID); ourClient.SendBulkUpdateInventory(item); // invalid the change item on viewer cache } else { m_Scene.AssetService.Store(m_asset); if (m_asset.FullID != UUID.Zero) { item.AssetID = m_asset.FullID; m_Scene.InventoryService.UpdateItem(item); } ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0); m_transactions.RemoveXferUploader(m_transactionID); m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0); } return(perms != 0); }
private void TaskInventoryOfferDecline(IClientAPI client, Scene scene, GridInstantMessage im) { // The inventory item/folder, back from it's trip UUID inventoryEntityID = new UUID(im.imSessionID); // Here, the recipient is local and we can assume that the inventory is loaded. // Courtesy of the above bulk update, it will have been pushed to the client, too. CachedUserInfo userInfo = scene.CommsManager.UserService.GetUserDetails(client.AgentId); if (userInfo != null) { InventoryFolderBase trashFolder = userInfo.FindFolderForType((int)AssetType.TrashFolder); if (null == trashFolder) { client.SendAgentAlertMessage("Unable to decline received inventory: Trash folder not found.", false); return; } // Is it a folder or an item? if (userInfo.QueryItem(inventoryEntityID)) { // It's an item. InventoryItemBase item = userInfo.FindItem(inventoryEntityID); if (item == null) { client.SendAgentAlertMessage("Unable to decline received inventory: item/folder not found.", false); return; } userInfo.MoveItemToTrash(item, trashFolder); scene.AddInventoryItem(client, item); client.SendInventoryItemCreateUpdate(item, 0); } else { // It's a folder. InventoryFolderBase folder = userInfo.GetFolderAttributes(inventoryEntityID); userInfo.MoveFolder(inventoryEntityID, trashFolder.ID); folder = userInfo.GetFolder(inventoryEntityID); if (folder != null) { client.SendBulkUpdateInventory(folder); // If we don't send the descendents, viewer shows "Loading..." on the trash item. userInfo.SendInventoryDecendents(client, folder.ID, false, true); } } } }
// // These 2 are for local and foreign users coming back, respectively // private void ProcessInventoryForComingHome(IClientAPI client) { if (!client.IsActive) { return; } m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Restoring root folder for local user {0}", client.Name); InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); List <InventoryFolderBase> keep = new List <InventoryFolderBase>(); foreach (InventoryFolderBase f in content.Folders) { if (f.Name != "My Suitcase" && f.Name != "Current Outfit") { keep.Add(f); } } client.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); }
private void TaskInventoryOfferAccept(IClientAPI client, Scene scene, GridInstantMessage im) { InventoryFolderBase folder = null; InventoryItemBase item = null; // The inventory item/folder, back from it's trip UUID inventoryEntityID = new UUID(im.imSessionID); // Here, the recipient is local and we can assume that the inventory is loaded. // Courtesy of the above bulk update, it will have been pushed to the client, too. CachedUserInfo userInfo = scene.CommsManager.UserService.GetUserDetails(client.AgentId); if (userInfo != null) { // Is it a folder or an item? if (userInfo.QueryItem(inventoryEntityID)) { // It's an item. item = userInfo.FindItem(inventoryEntityID); if (item == null) { client.SendAgentAlertMessage("Unable to accept received inventory: item/folder not found.", false); return; } client.SendInventoryItemCreateUpdate(item, 0); } else { // It's a folder. folder = userInfo.GetFolder(inventoryEntityID); if (folder != null) { client.SendBulkUpdateInventory(folder); // If we don't send the descendents, viewer shows "Loading..." on the trash item. userInfo.SendInventoryDecendents(client, folder.ID, false, true); } } } // RelayInventoryOfferIM(scene, im); // we don't need to notify a box that the user accepted this }
// // These 2 are for local and foreign users going away respectively // private void ProcessInventoryForHypergriding(IClientAPI client) { if (!client.IsActive) { return; } InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); if (root != null) { m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name); InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); List <InventoryFolderBase> keep = new List <InventoryFolderBase>(); foreach (InventoryFolderBase f in content.Folders) { if (f.Name != "My Suitcase" && f.Name != "Current Outfit") { f.Name = f.Name + " (Unavailable)"; keep.Add(f); } } // items directly under the root folder foreach (InventoryItemBase it in content.Items) { it.Name = it.Name + " (Unavailable)"; } ; // Send the new names client.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); } }
private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { // m_log.DebugFormat( // "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}", // (InstantMessageDialog)im.dialog, client.Name, // im.fromAgentID, im.fromAgentName, im.toAgentID); Scene scene = FindClientScene(client.AgentId); if (scene == null) // Something seriously wrong here. { return; } UUID agentID = client.AgentId; switch ((InstantMessageDialog)im.dialog) { case InstantMessageDialog.InventoryOffered: { if (im.binaryBucket.Length < 17) // Invalid { return; } UUID recipientID = new UUID(im.toAgentID); ScenePresence recipientAgent = scene.GetScenePresence(recipientID); UUID copyID; // First byte is the asset type AssetType assetType = (AssetType)im.binaryBucket[0]; if (assetType == AssetType.LinkFolder || assetType == AssetType.Link) { client.SendAgentAlertMessage("Can't give a link. Nothing given.", false); return; } if (assetType == AssetType.Folder) { UUID folderID = new UUID(im.binaryBucket, 1); if (folderID == UUID.Zero) { client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); return; } Dictionary <UUID, AssetType> ids = new Dictionary <UUID, AssetType>(); ids[folderID] = assetType; if (im.binaryBucket.Length >= 34 && im.binaryBucket.Length % 17 == 0) { byte[] iddata = im.binaryBucket; for (int i = 17; i < im.binaryBucket.Length - 17; i += 17) { ids[new UUID(iddata, i + 1)] = (AssetType)im.binaryBucket[i]; } } m_log.DebugFormat("[INVENTORY TRANSFER]: offering folder {0} to agent {1}'s inventory", folderID, recipientID); InventoryFolderBase folderCopy = scene.GiveInventoryFolder(client, recipientID, agentID, folderID, UUID.Zero, ids); if (folderCopy == null) { client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); return; } copyID = folderCopy.ID; im.imSessionID = copyID.Guid; if (recipientAgent != null) { recipientAgent.ControllingClient.SendBulkUpdateInventory(folderCopy); } } else { UUID itemID = new UUID(im.binaryBucket, 1); if (itemID == UUID.Zero) { client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); return; } m_log.DebugFormat("[INVENTORY TRANSFER]: (giving) Inserting item {0} " + "into agent {1}'s inventory", itemID, recipientID); string message; InventoryItemBase itemCopy = scene.GiveInventoryItem(recipientID, agentID, itemID, out message); if (itemCopy == null) { client.SendAgentAlertMessage(message, false); return; } copyID = itemCopy.ID; if (recipientAgent != null) { recipientAgent.ControllingClient.SendBulkUpdateInventory(itemCopy); } im.imSessionID = copyID.Guid; } // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. im.binaryBucket = new byte[17]; im.binaryBucket[0] = (byte)assetType; copyID.ToBytes(im.binaryBucket, 1); if (recipientAgent != null) { im.offline = 0; recipientAgent.ControllingClient.SendInstantMessage(im); return; } else { im.offline = 0; if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) { if (!success) { client.SendAlertMessage("User not online. Inventory has been saved"); } }); } } break; } case InstantMessageDialog.InventoryAccepted: { UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip if (inventoryID == UUID.Zero) { return; } IInventoryService invService = scene.InventoryService; ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); } } break; } case InstantMessageDialog.TaskInventoryAccepted: { if (im.binaryBucket == null || im.binaryBucket.Length < 16) { return; } UUID destinationFolderID = new UUID(im.binaryBucket, 0); if (destinationFolderID == UUID.Zero) // uuid-zero is a valid folder ID(?) keeping old code assuming not { return; } IInventoryService invService = scene.InventoryService; InventoryFolderBase destinationFolder = null; destinationFolder = invService.GetFolder(agentID, destinationFolderID); if (destinationFolder == null) { return; // no where to put it } UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip if (inventoryID == UUID.Zero) { return; } InventoryItemBase item = invService.GetItem(agentID, inventoryID); InventoryFolderBase folder = null; //UUID? previousParentFolderID = null; if (item != null) // It's an item { if (item.Folder != destinationFolderID) { //previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.MoveItems(item.Owner, new List <InventoryItemBase>() { item }); client.SendInventoryItemCreateUpdate(item, 0); } } else { folder = invService.GetFolder(agentID, inventoryID); if (folder != null) // It's a folder { if (folder.ParentID != destinationFolderID) { folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } client.SendBulkUpdateInventory(folder, folder.ID); } } break; } case InstantMessageDialog.InventoryDeclined: case InstantMessageDialog.TaskInventoryDeclined: { IInventoryService invService = scene.InventoryService; InventoryFolderBase trashFolder = invService.GetFolderForType(agentID, FolderType.Trash); if (trashFolder == null) //?? { client.SendAgentAlertMessage("Trash folder not found", false); return; } UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip if (inventoryID == UUID.Zero) { client.SendAgentAlertMessage("Item or folder not found", false); return; } InventoryItemBase item = invService.GetItem(agentID, inventoryID); InventoryFolderBase folder = null; if (item != null) { if (trashFolder.ID != item.Folder) { item.Folder = trashFolder.ID; invService.MoveItems(item.Owner, new List <InventoryItemBase>() { item }); client.SendInventoryItemCreateUpdate(item, 0); } } else { folder = invService.GetFolder(agentID, inventoryID); if (folder != null) { if (trashFolder.ID != folder.ParentID) { folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); } client.SendBulkUpdateInventory(folder, folder.ID); } } if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) { ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); } } } break; } default: break; } }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// <remarks> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// </remarks> /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); // Rez object InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); if (item != null) { item.Owner = remoteClient.AgentId; AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); SceneObjectGroup group = null; if (rezAsset != null) { UUID itemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { itemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world itemId = item.ID; } } string xmlData = Utils.BytesToString(rezAsset.Data); List <SceneObjectGroup> objlist = new List <SceneObjectGroup>(); List <Vector3> veclist = new List <Vector3>(); XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlData); XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); if (e == null || attachment) // Single { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat( itemId, xmlData); objlist.Add(g); veclist.Add(new Vector3(0, 0, 0)); float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; } else { XmlElement coll = (XmlElement)e; float bx = Convert.ToSingle(coll.GetAttribute("x")); float by = Convert.ToSingle(coll.GetAttribute("y")); float bz = Convert.ToSingle(coll.GetAttribute("z")); Vector3 bbox = new Vector3(bx, by, bz); pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, bbox, false); pos -= bbox / 2; XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); foreach (XmlNode n in groups) { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat( itemId, n.OuterXml); objlist.Add(g); XmlElement el = (XmlElement)n; string rawX = el.GetAttribute("offsetx"); string rawY = el.GetAttribute("offsety"); string rawZ = el.GetAttribute("offsetz"); // // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>", // g.Name, rawX, rawY, rawZ); float x = Convert.ToSingle(rawX); float y = Convert.ToSingle(rawY); float z = Convert.ToSingle(rawZ); veclist.Add(new Vector3(x, y, z)); } } int primcount = 0; foreach (SceneObjectGroup g in objlist) { primcount += g.PrimCount; } if (!m_Scene.Permissions.CanRezObject( primcount, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) { remoteClient.SendBulkUpdateInventory(item); } return(null); } for (int i = 0; i < objlist.Count; i++) { group = objlist[i]; Vector3 storedPosition = group.AbsolutePosition; if (group.UUID == UUID.Zero) { m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); } group.RootPart.FromFolderID = item.Folder; // If it's rezzed in world, select it. Much easier to // find small items. // if (!attachment) { group.RootPart.CreateSelected = true; foreach (SceneObjectPart child in group.Parts) { child.CreateSelected = true; } } group.ResetIDs(); if (attachment) { group.RootPart.Flags |= PrimFlags.Phantom; group.RootPart.IsAttachment = true; } // If we're rezzing an attachment then don't ask // AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than // one full update during the attachment // process causes some clients to fail to display the // attachment properly. m_Scene.AddNewSceneObject(group, true, false); // if attachment we set it's asset id so object updates // can reflect that, if not, we set it's position in world. if (!attachment) { group.ScheduleGroupForFullUpdate(); group.AbsolutePosition = pos + veclist[i]; } else { group.SetFromItemID(itemID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); } catch (NullReferenceException) { string isAttachment = ""; if (attachment) { isAttachment = " Object was an attachment"; } m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); } // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectPart part in group.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } part.GroupMask = 0; // DO NOT propagate here } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in group.Parts) { if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); part.GroupMask = 0; // DO NOT propagate here } part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } } if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List <UUID> uuids = new List <UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } } return(group); } return(null); }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// <remarks> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// </remarks> /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { // m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); // Rez object InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); if (item != null) { item.Owner = remoteClient.AgentId; AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); SceneObjectGroup group = null; if (rezAsset != null) { UUID itemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { itemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world itemId = item.ID; } } string xmlData = Utils.BytesToString(rezAsset.Data); List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); List<Vector3> veclist = new List<Vector3>(); XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlData); XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); if (e == null || attachment) // Single { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat( itemId, xmlData); objlist.Add(g); veclist.Add(new Vector3(0, 0, 0)); float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; } else { XmlElement coll = (XmlElement)e; float bx = Convert.ToSingle(coll.GetAttribute("x")); float by = Convert.ToSingle(coll.GetAttribute("y")); float bz = Convert.ToSingle(coll.GetAttribute("z")); Vector3 bbox = new Vector3(bx, by, bz); pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, bbox, false); pos -= bbox / 2; XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); foreach (XmlNode n in groups) { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat( itemId, n.OuterXml); objlist.Add(g); XmlElement el = (XmlElement)n; string rawX = el.GetAttribute("offsetx"); string rawY = el.GetAttribute("offsety"); string rawZ = el.GetAttribute("offsetz"); // // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>", // g.Name, rawX, rawY, rawZ); float x = Convert.ToSingle(rawX); float y = Convert.ToSingle(rawY); float z = Convert.ToSingle(rawZ); veclist.Add(new Vector3(x, y, z)); } } int primcount = 0; foreach (SceneObjectGroup g in objlist) primcount += g.PrimCount; if (!m_Scene.Permissions.CanRezObject( primcount, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); return null; } for (int i = 0 ; i < objlist.Count ; i++ ) { group = objlist[i]; Vector3 storedPosition = group.AbsolutePosition; if (group.UUID == UUID.Zero) { m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); } group.RootPart.FromFolderID = item.Folder; // If it's rezzed in world, select it. Much easier to // find small items. // if (!attachment) { group.RootPart.CreateSelected = true; foreach (SceneObjectPart child in group.Parts) child.CreateSelected = true; } group.ResetIDs(); if (attachment) { group.RootPart.Flags |= PrimFlags.Phantom; group.RootPart.IsAttachment = true; } // If we're rezzing an attachment then don't ask // AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than // one full update during the attachment // process causes some clients to fail to display the // attachment properly. m_Scene.AddNewSceneObject(group, true, false); // if attachment we set it's asset id so object updates // can reflect that, if not, we set it's position in world. if (!attachment) { group.ScheduleGroupForFullUpdate(); group.AbsolutePosition = pos + veclist[i]; } else { group.SetFromItemID(itemID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); } catch (NullReferenceException) { string isAttachment = ""; if (attachment) isAttachment = " Object was an attachment"; m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); } // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectPart part in group.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } part.GroupMask = 0; // DO NOT propagate here } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in group.Parts) { if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); part.GroupMask = 0; // DO NOT propagate here } part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) group.ClearPartAttachmentData(); // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } } if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List<UUID> uuids = new List<UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } } return group; } return null; }
private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Group invitations if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = new UUID(im.imSessionID); GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); if (inviteInfo == null) { if (m_debugEnabled) m_log.WarnFormat("[GROUPS]: Received an Invite IM for an invite that does not exist {0}.", inviteID); return; } if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Invite is for Agent {0} to Group {1}.", inviteInfo.AgentID, inviteInfo.GroupID); UUID fromAgentID = new UUID(im.fromAgentID); if ((inviteInfo != null) && (fromAgentID == inviteInfo.AgentID)) { // Accept if (im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; msg.fromAgentID = UUID.Zero.Guid; msg.toAgentID = inviteInfo.AgentID.Guid; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = "Groups"; msg.message = string.Format("You have been added to the group."); msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox; msg.fromGroup = false; msg.offline = (byte)0; msg.ParentEstateID = 0; msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; msg.binaryBucket = new byte[0]; OutgoingInstantMessage(msg, inviteInfo.AgentID); //WTH??? noone but the invitee needs to know //UpdateAllClientsWithGroupInfo(inviteInfo.AgentID); SendAgentGroupDataUpdate(remoteClient); // XTODO: If the inviter is still online, they need an agent dataupdate // and maybe group membership updates for the invitee // Reply: why do they need that? they will get told about the new user when they reopen the groups panel m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } // Reject if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice."); m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } } } // Group notices if ((im.dialog == (byte)InstantMessageDialog.GroupNotice)) { if (!m_groupNoticesEnabled) return; UUID GroupID = new UUID(im.toAgentID); if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.message.Substring(0, im.message.IndexOf('|')); string Message = im.message.Substring(Subject.Length + 1); byte[] bucket; UUID ItemID = UUID.Zero; int AssetType = 0; string ItemName = ""; if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) { bucket = new byte[19]; bucket[0] = 0; bucket[1] = 0; GroupID.ToBytes(bucket, 2); bucket[18] = 0; } else { bucket = im.binaryBucket; string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); binBucket = binBucket.Remove(0, 14).Trim(); OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); if (binBucketOSD.ContainsKey("item_id")) { ItemID = binBucketOSD["item_id"].AsUUID(); InventoryItemBase item = new InventoryItemBase(ItemID, GetRequestingAgentID(remoteClient)); item = m_sceneList[0].InventoryService.GetItem(item); if (item != null) { AssetType = item.AssetType; ItemName = item.Name; } else ItemID = UUID.Zero; } } m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, ItemID, AssetType, ItemName); if (OnNewGroupNotice != null) OnNewGroupNotice(GroupID, NoticeID); // Send notice out to everyone that wants notices foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) { if (m_debugEnabled) { UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); if (targetUser != null) { m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); } else { m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); } } if (member.AcceptNotices) { // Build notice IIM GridInstantMessage msg = CreateGroupNoticeIM(GetRequestingAgentID(remoteClient), NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); msg.toAgentID = member.AgentID.Guid; OutgoingInstantMessage(msg, member.AgentID); } } } } if ((im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined) || (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined)) { GroupAttachmentCache.Remove(im.imSessionID); } if ((im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted) || (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)) { UUID FolderID = new UUID(im.binaryBucket, 0); InventoryItemBase item = new InventoryItemBase(GroupAttachmentCache[im.imSessionID]); item = ((Scene)remoteClient.Scene).InventoryService.GetItem(item); ILLClientInventory inventoryModule = remoteClient.Scene.RequestModuleInterface<ILLClientInventory>(); if (inventoryModule != null) item = inventoryModule.GiveInventoryItem(remoteClient.AgentId, item.Owner, GroupAttachmentCache[im.imSessionID], FolderID); if (item != null) remoteClient.SendBulkUpdateInventory(item); GroupAttachmentCache.Remove(im.imSessionID); } if ((im.dialog == 210)) { // This is sent from the region that the ejectee was ejected from // if it's being delivered here, then the ejectee is here // so we need to send local updates to the agent. UUID ejecteeID = new UUID(im.toAgentID); im.dialog = (byte)InstantMessageDialog.MessageFromAgent; OutgoingInstantMessage(im, ejecteeID); IClientAPI ejectee = GetActiveClient(ejecteeID); if (ejectee != null) { UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); } } // Interop, received special 211 code for offline group notice if ((im.dialog == 211)) { im.dialog = (byte)InstantMessageDialog.GroupNotice; //In offline group notices, imSessionID is replaced with the NoticeID so that we can rebuild the packet here GroupNoticeInfo GND = m_groupData.GetGroupNotice(new UUID(im.toAgentID), new UUID(im.imSessionID)); //We reset the ID so that if this was set before, it won't be misadded or anything to the cache im.imSessionID = UUID.Random().Guid; //Rebuild the binary bucket if (GND.noticeData.HasAttachment) { im.binaryBucket = CreateBitBucketForGroupAttachment(GND.noticeData, GND.GroupID); //Save the sessionID for the callback by the client (reject or accept) //Only save if has attachment GroupAttachmentCache[im.imSessionID] = GND.noticeData.ItemID; } else { byte[] bucket = new byte[19]; bucket[0] = 0; //Attachment enabled == false so 0 bucket[1] = 0; //No attachment, so no asset type GND.GroupID.ToBytes(bucket, 2); bucket[18] = 0; //dunno im.binaryBucket = bucket; } OutgoingInstantMessage(im, new UUID(im.toAgentID)); //You MUST reset this, otherwise the client will get it twice, // as it goes through OnGridInstantMessage // which will check and then reresent the notice im.dialog = 211; } }
public virtual SceneObjectGroup RezObject( IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); if (rezAsset == null) { if (item != null) { m_log.WarnFormat( "[InventoryAccessModule]: Could not find asset {0} for item {1} {2} for {3} in RezObject()", assetID, item.Name, item.ID, remoteClient.Name); remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0} for item {1}.", assetID, item.Name), false); } else { m_log.WarnFormat( "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()", assetID, remoteClient.Name); remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: could not find asset {0}.", assetID), false); } return null; } SceneObjectGroup group = null; List<SceneObjectGroup> objlist; List<Vector3> veclist; Vector3 bbox; float offsetHeight; byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); Vector3 pos; bool single = m_Scene.GetObjectsToRez( rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); if (single) { pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, bbox, false); pos.Z += offsetHeight; } else { pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, bbox, false); pos -= bbox / 2; } int primcount = 0; foreach (SceneObjectGroup g in objlist) primcount += g.PrimCount; if (!m_Scene.Permissions.CanRezObject( primcount, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (item != null) { if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); } return null; } if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) return null; for (int i = 0; i < objlist.Count; i++) { group = objlist[i]; SceneObjectPart rootPart = group.RootPart; // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", // group.Name, group.LocalId, group.UUID, // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, // remoteClient.Name); // Vector3 storedPosition = group.AbsolutePosition; if (group.UUID == UUID.Zero) { m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); } // if this was previously an attachment and is now being rezzed, // save the old attachment info. if (group.IsAttachment == false && group.RootPart.Shape.State != 0) { group.RootPart.AttachedPos = group.AbsolutePosition; group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; } if (item == null) { // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here. foreach (SceneObjectPart part in group.Parts) { // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. part.LastOwnerID = part.OwnerID; part.OwnerID = remoteClient.AgentId; } } group.ResetIDs(); if (!attachment) { // If it's rezzed in world, select it. Much easier to // find small items. // foreach (SceneObjectPart part in group.Parts) { part.CreateSelected = true; } if (rootPart.Shape.PCode == (byte)PCode.Prim) group.ClearPartAttachmentData(); } else { group.IsAttachment = true; } // If we're rezzing an attachment then don't ask // AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than // one full update during the attachment // process causes some clients to fail to display the // attachment properly. m_Scene.AddNewSceneObject(group, true, false); if (!attachment) group.AbsolutePosition = pos + veclist[i]; group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (!attachment) { // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); rootPart.ParentGroup.ResumeScripts(); group.ScheduleGroupForFullUpdate(); } // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", // group.Name, group.LocalId, group.UUID, // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, // remoteClient.Name); } // group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (item != null) DoPostRezWhenFromItem(item, attachment); return group; }
private List <SceneObjectGroup> RezMultipleObjectsFromInventory(XmlNodeList nodes, UUID itemId, IClientAPI remoteClient, Vector3 pos, bool RezSelected, InventoryItemBase item, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, Vector3 RayEnd, Vector3 RayStart, byte bRayEndIsIntersection) { Vector3 OldMiddlePos = Vector3.Zero; List <SceneObjectGroup> NewGroup = new List <SceneObjectGroup>(); foreach (System.Xml.XmlNode aPrimNode in nodes) { if (aPrimNode.OuterXml.StartsWith("<middle>")) { string Position = aPrimNode.OuterXml.Remove(0, 13); Position = Position.Remove(Position.Length - 16, 16); string[] XYZ = Position.Split(' '); OldMiddlePos = new Vector3(float.Parse(XYZ[0]), float.Parse(XYZ[1]), float.Parse(XYZ[2])); continue; } SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(aPrimNode.OuterXml, m_scene); if (group == null) { return(null); } group.IsDeleted = false; group.m_isLoaded = true; foreach (SceneObjectPart part in group.ChildrenList) { part.IsLoading = false; } NewGroup.Add(group); string reason; if (!m_scene.Permissions.CanRezObject( group.ChildrenList.Count, remoteClient.AgentId, pos, out reason)) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)) { remoteClient.SendBulkUpdateInventory(item); } return(null); } if (RezSelected) { group.RootPart.AddFlag(PrimFlags.CreateSelected); } // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_scene.SceneGraph.AddPrimToScene(group); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. float offsetHeight = 0; pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; //group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); SceneObjectPart rootPart = (SceneObjectPart)group.GetChildPart(group.UUID); // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart>(group.ChildrenList); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); item.Owner = remoteClient.AgentId; if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, 0, UUID.Zero); rootPart.ParentGroup.ResumeScripts(); if (!m_scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // List <UUID> uuids = new List <UUID>(); uuids.Add(item.ID); m_scene.InventoryService.DeleteItems(item.Owner, uuids); } } } foreach (SceneObjectGroup group in NewGroup) { if (OldMiddlePos != Vector3.Zero) { Vector3 NewPosOffset = Vector3.Zero; NewPosOffset.X = group.AbsolutePosition.X - OldMiddlePos.X; NewPosOffset.Y = group.AbsolutePosition.Y - OldMiddlePos.Y; NewPosOffset.Z = group.AbsolutePosition.Z - OldMiddlePos.Z; group.AbsolutePosition = pos + NewPosOffset; } group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate); } return(NewGroup); }
/// <summary> /// Give an inventory item from one user to another /// </summary> /// <param name="recipientClient"></param> /// <param name="senderId">ID of the sender of the item</param> /// <param name="itemId"></param> public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) { InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); if (itemCopy != null) recipientClient.SendBulkUpdateInventory(itemCopy); }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual ISceneEntity RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID) { // Work out position details byte bRayEndIsIntersection = (byte) 0; bRayEndIsIntersection = (byte) (RayEndIsIntersection ? 1 : 0); XmlDocument doc; //It might be a library item, send UUID.Zero InventoryItemBase item = m_scene.InventoryService.GetItem(UUID.Zero, itemID); if (item == null) { remoteClient.SendAlertMessage("Failed to find the item you requested."); return null; } ISceneEntity group = CreateObjectFromInventory(item, remoteClient, itemID, out doc); Vector3 pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, new Vector3(0.5f, 0.5f, 0.5f), false); if (doc == null) { //No asset, check task inventory IEntity e; m_scene.SceneGraph.TryGetEntity(fromTaskID, out e); if (e != null && e is ISceneEntity) { ISceneEntity grp = (ISceneEntity) e; TaskInventoryItem taskItem = grp.RootChild.Inventory.GetInventoryItem(itemID); item = new InventoryItemBase { ID = UUID.Random(), CreatorId = taskItem.CreatorID.ToString(), Owner = remoteClient.AgentId, AssetID = taskItem.AssetID, Description = taskItem.Description, Name = taskItem.Name, AssetType = taskItem.Type, InvType = taskItem.InvType, Flags = taskItem.Flags, SalePrice = taskItem.SalePrice, SaleType = taskItem.SaleType }; if (m_scene.Permissions.PropagatePermissions()) { item.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint) PermissionMask.Move); if (taskItem.InvType == (int) InventoryType.Object) item.CurrentPermissions = item.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint) PermissionMask.Move)); else item.CurrentPermissions = item.BasePermissions & taskItem.CurrentPermissions; item.CurrentPermissions |= 16; // Slam item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint) PermissionMask.Move); item.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; } else { item.BasePermissions = taskItem.BasePermissions; item.CurrentPermissions = taskItem.CurrentPermissions; item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions; item.GroupPermissions = taskItem.GroupPermissions; } group = CreateObjectFromInventory(item, remoteClient, itemID, out doc); } } if (group == null && doc != null && doc.FirstChild != null && (doc.FirstChild.OuterXml.StartsWith("<groups>") || (doc.FirstChild.NextSibling != null && doc.FirstChild.NextSibling.OuterXml.StartsWith("<groups>")))) { XmlNodeList nodes; if (doc.FirstChild.OuterXml.StartsWith("<groups>")) nodes = doc.FirstChild.ChildNodes; else if (doc.FirstChild.NextSibling != null) nodes = doc.FirstChild.NextSibling.ChildNodes; else { remoteClient.SendAlertMessage("Failed to find the item you requested."); return null; } List<ISceneEntity> Groups = RezMultipleObjectsFromInventory(nodes, itemID, remoteClient, pos, RezSelected, item, RayTargetID, BypassRayCast, RayEndIsIntersection, RayEnd, RayStart, bRayEndIsIntersection); if (Groups.Count != 0) return Groups[0]; remoteClient.SendAlertMessage("Failed to rez the item you requested."); return null; } if (group == null) { remoteClient.SendAlertMessage("Failed to find the item you requested."); return null; } string reason; if (!m_scene.Permissions.CanRezObject( group.ChildrenEntities().Count, remoteClient.AgentId, pos, out reason)) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if ((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0) remoteClient.SendBulkUpdateInventory(item); remoteClient.SendAlertMessage("You do not have permission to rez objects here."); return null; } if (RezSelected) group.RootChild.AddFlag(PrimFlags.CreateSelected); // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_scene.SceneGraph.AddPrimToScene(group); // MainConsole.Instance.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // Set it's position in world. const float offsetHeight = 0; //The OOBsize is only half the size, x2 Vector3 newSize = (group.OOBsize*2)*Quaternion.Inverse(group.GroupRotation); pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, newSize, false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // MainConsole.Instance.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); ISceneChildEntity rootPart = group.GetChildPart(group.UUID); if (rootPart == null) { MainConsole.Instance.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart."); return null; } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List<ISceneChildEntity> partList = group.ChildrenEntities(); group.SetGroup(remoteClient.ActiveGroupId, remoteClient.AgentId, false); item.Owner = remoteClient.AgentId; if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (ISceneChildEntity part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (ISceneChildEntity part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (group.RootChild.Shape.PCode == (byte) PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, StateSource.NewRez, UUID.Zero, false); group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); if (!m_scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0) { List<UUID> uuids = new List<UUID> {item.ID}; m_scene.InventoryService.DeleteItems(item.Owner, uuids); } } return group; }
private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) MainConsole.Instance.DebugFormat("[GROUPS]: {0} called", MethodBase.GetCurrentMethod().Name); // Group invitations if ((im.Dialog == (byte) InstantMessageDialog.GroupInvitationAccept) || (im.Dialog == (byte) InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = im.SessionID; GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); if (inviteInfo == null) { if (m_debugEnabled) MainConsole.Instance.WarnFormat( "[GROUPS]: Received an Invite IM for an invite that does not exist {0}.", inviteID); return; } if (m_debugEnabled) MainConsole.Instance.DebugFormat("[GROUPS]: Invite is for Agent {0} to Group {1}.", inviteInfo.AgentID, inviteInfo.GroupID); UUID fromAgentID = im.FromAgentID; if ((inviteInfo != null) && (fromAgentID == inviteInfo.AgentID)) { // Accept if (im.Dialog == (byte) InstantMessageDialog.GroupInvitationAccept) { if (m_debugEnabled) MainConsole.Instance.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role UserAccount account = m_scene.UserAccountService.GetUserAccount(remoteClient.AllScopeIDs, inviteInfo.FromAgentName); if (account != null) { m_groupData.AddAgentToGroup(account.PrincipalID, inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage { SessionID = UUID.Zero, FromAgentID = UUID.Zero, ToAgentID = inviteInfo.AgentID, Timestamp = (uint) Util.UnixTimeSinceEpoch(), FromAgentName = "Groups", Message = string.Format("You have been added to the group."), Dialog = (byte) InstantMessageDialog.MessageBox, FromGroup = false, Offline = 0, ParentEstateID = 0, Position = Vector3.Zero, RegionID = UUID.Zero, BinaryBucket = new byte[0] }; OutgoingInstantMessage(msg, inviteInfo.AgentID); GroupMembershipData gmd = AttemptFindGroupMembershipData(inviteInfo.AgentID, inviteInfo.AgentID, inviteInfo.GroupID); m_cachedGroupTitles[inviteInfo.AgentID] = gmd; m_cachedGroupMemberships.Remove(remoteClient.AgentId); RemoveFromGroupPowersCache(inviteInfo.AgentID, inviteInfo.GroupID); UpdateAllClientsWithGroupInfo(inviteInfo.AgentID, gmd.GroupTitle); SendAgentGroupDataUpdate(remoteClient); m_groupData.RemoveAgentInvite(GetRequestingAgentID(remoteClient), inviteID); } } // Reject if (im.Dialog == (byte) InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) MainConsole.Instance.DebugFormat("[GROUPS]: Received a reject invite notice."); m_groupData.RemoveAgentInvite(GetRequestingAgentID(remoteClient), inviteID); } RemoveFromGroupPowersCache(remoteClient.AgentId, inviteInfo.GroupID); } } // Group notices switch (im.Dialog) { case (byte) InstantMessageDialog.GroupNotice: { if (!m_groupNoticesEnabled) return; UUID GroupID = im.ToAgentID; if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.Message.Substring(0, im.Message.IndexOf('|')); string Message = im.Message.Substring(Subject.Length + 1); byte[] bucket; UUID ItemID = UUID.Zero; int AssetType = 0; string ItemName = ""; if ((im.BinaryBucket.Length == 1) && (im.BinaryBucket[0] == 0)) { bucket = new byte[19]; bucket[0] = 0; bucket[1] = 0; GroupID.ToBytes(bucket, 2); bucket[18] = 0; } else { bucket = im.BinaryBucket; string binBucket = Utils.BytesToString(im.BinaryBucket); binBucket = binBucket.Remove(0, 14).Trim(); OSDMap binBucketOSD = (OSDMap) OSDParser.DeserializeLLSDXml(binBucket); if (binBucketOSD.ContainsKey("item_id")) { ItemID = binBucketOSD["item_id"].AsUUID(); InventoryItemBase item = m_scene.InventoryService.GetItem(GetRequestingAgentID(remoteClient), ItemID); if (item != null) { AssetType = item.AssetType; ItemName = item.Name; } else ItemID = UUID.Zero; } } m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.FromAgentName, Subject, Message, ItemID, AssetType, ItemName); if (OnNewGroupNotice != null) OnNewGroupNotice(GroupID, NoticeID); GroupNoticeInfo notice = new GroupNoticeInfo() { BinaryBucket = im.BinaryBucket, GroupID = GroupID, Message = Message, noticeData = new GroupNoticeData() { AssetType = (byte) AssetType, FromName = im.FromAgentName, GroupID = GroupID, HasAttachment = ItemID != UUID.Zero, ItemID = ItemID, ItemName = ItemName, NoticeID = NoticeID, Subject = Subject, Timestamp = im.Timestamp } }; SendGroupNoticeToUsers(remoteClient, notice, false); } } break; case (byte) InstantMessageDialog.GroupNoticeInventoryDeclined: break; case (byte) InstantMessageDialog.GroupNoticeInventoryAccepted: { UUID FolderID = new UUID(im.BinaryBucket, 0); remoteClient.Scene.InventoryService.GiveInventoryItemAsync(remoteClient.AgentId, UUID.Zero, im.SessionID, FolderID, false, (item) => { if (item != null) remoteClient .SendBulkUpdateInventory (item); }); } break; case 210: { // This is sent from the region that the ejectee was ejected from // if it's being delivered here, then the ejectee is here // so we need to send local updates to the agent. UUID ejecteeID = im.ToAgentID; im.Dialog = (byte) InstantMessageDialog.MessageFromAgent; OutgoingInstantMessage(im, ejecteeID); IClientAPI ejectee = GetActiveClient(ejecteeID); if (ejectee != null) { UUID groupID = im.SessionID; ejectee.SendAgentDropGroup(groupID); if (ejectee.ActiveGroupId == groupID) GroupTitleUpdate(ejectee, UUID.Zero, UUID.Zero); RemoveFromGroupPowersCache(ejecteeID, groupID); } } break; case 211: { im.Dialog = (byte) InstantMessageDialog.GroupNotice; //In offline group notices, imSessionID is replaced with the NoticeID so that we can rebuild the packet here GroupNoticeInfo GND = m_groupData.GetGroupNotice(im.ToAgentID, im.SessionID); //Rebuild the binary bucket if (GND.noticeData.HasAttachment) { im.BinaryBucket = CreateBitBucketForGroupAttachment(GND.noticeData, GND.GroupID); //Save the sessionID for the callback by the client (reject or accept) //Only save if has attachment im.SessionID = GND.noticeData.ItemID; } else { byte[] bucket = new byte[19]; bucket[0] = 0; //Attachment enabled == false so 0 bucket[1] = 0; //No attachment, so no asset type GND.GroupID.ToBytes(bucket, 2); bucket[18] = 0; //dunno im.BinaryBucket = bucket; } OutgoingInstantMessage(im, im.ToAgentID); //You MUST reset this, otherwise the client will get it twice, // as it goes through OnGridInstantMessage // which will check and then reresent the notice im.Dialog = 211; } break; } }
/// <summary> /// Do pre-rez processing when the object comes from an item. /// </summary> /// <param name="remoteClient"></param> /// <param name="item"></param> /// <param name="objlist"></param> /// <param name="pos"></param> /// <param name="veclist"> /// List of vector position adjustments for a coalesced objects. For ordinary objects /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist /// </param> /// <param name="isAttachment"></param> /// <returns>true if we can processed with rezzing, false if we need to abort</returns> private bool DoPreRezWhenFromItem( IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, List<Vector3> veclist, bool isAttachment) { UUID fromUserInventoryItemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { fromUserInventoryItemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world fromUserInventoryItemId = item.ID; } } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup g = objlist[i]; if (!m_Scene.Permissions.CanRezObject( g.PrimCount, remoteClient.AgentId, pos + veclist[i]) && !isAttachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) remoteClient.SendBulkUpdateInventory(item); ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); remoteClient.SendAlertMessage(string.Format( "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name)); return false; } } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup so = objlist[i]; SceneObjectPart rootPart = so.RootPart; // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } so.FromFolderID = item.Folder; // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", // rootPart.OwnerID, item.Owner, item.CurrentPermissions); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectPart part in so.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } part.GroupMask = 0; // DO NOT propagate here } so.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in so.Parts) { part.FromUserInventoryItemID = fromUserInventoryItemId; if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.Inventory.ChangeInventoryOwner(item.Owner); part.GroupMask = 0; // DO NOT propagate here } part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); if (isAttachment) so.FromItemID = item.ID; } return true; }
/// <summary> /// Do pre-rez processing when the object comes from an item. /// </summary> /// <param name="remoteClient"></param> /// <param name="item"></param> /// <param name="objlist"></param> /// <param name="pos"></param> /// <param name="isAttachment"></param> /// <returns>true if we can processed with rezzing, false if we need to abort</returns> private bool DoPreRezWhenFromItem( IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) { UUID fromUserInventoryItemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { fromUserInventoryItemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world fromUserInventoryItemId = item.ID; } } int primcount = 0; foreach (SceneObjectGroup g in objlist) primcount += g.PrimCount; if (!m_Scene.Permissions.CanRezObject( primcount, remoteClient.AgentId, pos) && !isAttachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) remoteClient.SendBulkUpdateInventory(item); return false; } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup so = objlist[i]; SceneObjectPart rootPart = so.RootPart; // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } rootPart.FromFolderID = item.Folder; if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectPart part in so.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } part.GroupMask = 0; // DO NOT propagate here } so.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in so.Parts) { part.FromUserInventoryItemID = fromUserInventoryItemId; if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.Inventory.ChangeInventoryOwner(item.Owner); part.GroupMask = 0; // DO NOT propagate here } part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); if (isAttachment) so.SetFromItemID(item.ID); } return true; }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { // Work out position details byte bRayEndIsIntersection = (byte)0; if (RayEndIsIntersection) { bRayEndIsIntersection = (byte)1; } else { bRayEndIsIntersection = (byte)0; } Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); // Rez object InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); if (item != null) { AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); if (rezAsset != null) { UUID itemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) { itemId = item.ID; } } else { // Brave new fullperm world // itemId = item.ID; } string xmlData = Utils.BytesToString(rezAsset.Data); SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) { remoteClient.SendBulkUpdateInventory(item); } return(null); } group.ResetIDs(); if (attachment) { group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom; group.RootPart.IsAttachment = true; } // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_Scene.AddNewSceneObject(group, true, false); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. if (!attachment) { group.ScheduleGroupForFullUpdate(); float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); } else { group.SetFromItemID(itemID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); } catch (NullReferenceException) { string isAttachment = ""; if (attachment) { isAttachment = " Object was an attachment"; } m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart>(group.Children.Values); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List <UUID> uuids = new List <UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } return(rootPart.ParentGroup); } } return(null); }
private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { // m_log.DebugFormat( // "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}", // (InstantMessageDialog)im.dialog, client.Name, // im.fromAgentID, im.fromAgentName, im.toAgentID); Scene scene = FindClientScene(client.AgentId); if (scene == null) // Something seriously wrong here. { return; } if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) { //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); if (im.binaryBucket.Length < 17) // Invalid { return; } UUID recipientID = new UUID(im.toAgentID); ScenePresence user = scene.GetScenePresence(recipientID); UUID copyID; // First byte is the asset type AssetType assetType = (AssetType)im.binaryBucket[0]; if (AssetType.Folder == assetType) { UUID folderID = new UUID(im.binaryBucket, 1); m_log.DebugFormat( "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", folderID, new UUID(im.toAgentID)); InventoryFolderBase folderCopy = scene.GiveInventoryFolder(client, recipientID, client.AgentId, folderID, UUID.Zero); if (folderCopy == null) { client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); return; } // The outgoing binary bucket should contain only the byte which signals an asset folder is // being copied and the following bytes for the copied folder's UUID copyID = folderCopy.ID; byte[] copyIDBytes = copyID.GetBytes(); im.binaryBucket = new byte[1 + copyIDBytes.Length]; im.binaryBucket[0] = (byte)AssetType.Folder; Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); if (user != null) { user.ControllingClient.SendBulkUpdateInventory(folderCopy); } // HACK!! // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it // is rejected. // XXX: This is probably a misuse of the session ID slot. im.imSessionID = copyID.Guid; } else { // First byte of the array is probably the item type // Next 16 bytes are the UUID UUID itemID = new UUID(im.binaryBucket, 1); m_log.DebugFormat("[INVENTORY TRANSFER]: (giving) Inserting item {0} " + "into agent {1}'s inventory", itemID, new UUID(im.toAgentID)); string message; InventoryItemBase itemCopy = scene.GiveInventoryItem(new UUID(im.toAgentID), client.AgentId, itemID, out message); if (itemCopy == null) { client.SendAgentAlertMessage(message, false); return; } copyID = itemCopy.ID; Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); if (user != null) { user.ControllingClient.SendBulkUpdateInventory(itemCopy); } // HACK!! // Insert the ID of the copied item into the IM so that we know which item to move to trash if it // is rejected. // XXX: This is probably a misuse of the session ID slot. im.imSessionID = copyID.Guid; } im.offline = 0; // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // if (user != null) { user.ControllingClient.SendInstantMessage(im); return; } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) { if (!success) { client.SendAlertMessage("User not online. Inventory has been saved"); } }); } } } else if (im.dialog == (byte)InstantMessageDialog.InventoryAccepted || im.dialog == (byte)InstantMessageDialog.TaskInventoryAccepted) { UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip IInventoryService invService = scene.InventoryService; // Special case: folder redirect. // RLV uses this if (im.dialog == (byte)InstantMessageDialog.TaskInventoryAccepted) { InventoryFolderBase folder = invService.GetFolder(client.AgentId, inventoryID); if (folder != null) { if (im.binaryBucket.Length >= 16) { UUID destFolderID = new UUID(im.binaryBucket, 0); if (destFolderID != UUID.Zero) { InventoryFolderBase destFolder = invService.GetFolder(client.AgentId, destFolderID); if (destFolder != null) { if (folder.ParentID != destFolder.ID) { folder.ParentID = destFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); } } } } } } ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); } } } // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name> // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet // happening, possibly because we are not sending the correct inventory update messages with the correct // transaction IDs else if (im.dialog == (byte)InstantMessageDialog.TaskInventoryAccepted) { UUID destinationFolderID = UUID.Zero; if (im.binaryBucket != null && im.binaryBucket.Length >= 16) { destinationFolderID = new UUID(im.binaryBucket, 0); } if (destinationFolderID != UUID.Zero) { InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); IInventoryService invService = scene.InventoryService; UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID); InventoryFolderBase folder = null; UUID?previousParentFolderID = null; if (item != null) // It's an item { previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.DeleteItems(item.Owner, new List <UUID>() { item.ID }); scene.AddInventoryItem(client, item); } else { folder = invService.GetFolder(client.AgentId, inventoryID); if (folder != null) // It's a folder { previousParentFolderID = folder.ParentID; folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } } // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). if (previousParentFolderID != null) { InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID); scene.SendInventoryUpdate(client, previousParentFolder, true, true); scene.SendInventoryUpdate(client, destinationFolder, true, true); } } } else if ( im.dialog == (byte)InstantMessageDialog.InventoryDeclined || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) { // Here, the recipient is local and we can assume that the // inventory is loaded. Courtesy of the above bulk update, // It will have been pushed to the client, too // IInventoryService invService = scene.InventoryService; InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, FolderType.Trash); UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID); InventoryFolderBase folder = null; UUID?previousParentFolderID = null; if (item != null && trashFolder != null) { previousParentFolderID = item.Folder; item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? List <UUID> uuids = new List <UUID>(); uuids.Add(item.ID); invService.DeleteItems(item.Owner, uuids); scene.AddInventoryItem(client, item); } else { folder = invService.GetFolder(client.AgentId, inventoryID); if (folder != null && trashFolder != null) { previousParentFolderID = folder.ParentID; folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); } } if ((null == item && null == folder) || null == trashFolder) { string reason = String.Empty; if (trashFolder == null) { reason += " Trash folder not found."; } if (item == null) { reason += " Item not found."; } if (folder == null) { reason += " Folder not found."; } client.SendAgentAlertMessage("Unable to delete " + "received inventory" + reason, false); } // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). else if (previousParentFolderID != null) { InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID); scene.SendInventoryUpdate(client, previousParentFolder, true, true); scene.SendInventoryUpdate(client, trashFolder, true, true); } if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) { ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); } } } } }
private void TaskInventoryOfferDecline(IClientAPI client, Scene scene, GridInstantMessage im) { // The inventory item/folder, back from it's trip UUID inventoryEntityID = new UUID(im.imSessionID); // Here, the recipient is local and we can assume that the inventory is loaded. // Courtesy of the above bulk update, it will have been pushed to the client, too. CachedUserInfo userInfo = scene.CommsManager.UserService.GetUserDetails(client.AgentId); if (userInfo != null) { InventoryFolderBase trashFolder = userInfo.FindFolderForType((int)FolderType.Trash); if (null == trashFolder) { client.SendAgentAlertMessage("Unable to decline received inventory: Trash folder not found.", false); return; } // Is it a folder or an item? if (userInfo.QueryItem(inventoryEntityID)) { // It's an item. InventoryItemBase item = userInfo.FindItem(inventoryEntityID); if (item == null) { client.SendAgentAlertMessage("Unable to decline received inventory: item/folder not found.", false); return; } userInfo.MoveItemToTrash(item, trashFolder); scene.AddInventoryItem(client, item); client.SendInventoryItemCreateUpdate(item, 0); } else { // It's a folder. InventoryFolderBase folder = userInfo.GetFolderAttributes(inventoryEntityID); userInfo.MoveFolder(inventoryEntityID, trashFolder.ID); folder = userInfo.GetFolder(inventoryEntityID); if (folder != null) { client.SendBulkUpdateInventory(folder); // If we don't send the descendents, viewer shows "Loading..." on the trash item. userInfo.SendInventoryDecendents(client, folder.ID, false, true); } } } }
/// <summary> /// Hot patches inventory items that may have the wrong flags set and thus will not wear in the viewer /// </summary> /// <param name="baseItem"></param> /// <param name="uinfo"></param> /// <param name="clientView"></param> /// <returns></returns> private bool FixupItemFlagsOnWearableTypeMismatch(InventoryItemBase baseItem, CachedUserInfo uinfo, IClientAPI clientView) { if (baseItem.InvType != (int)InventoryType.Wearable) return false; //download the asset and extract the type. make sure the type matches the lower byte //of the inventory item flags AssetBase asset; try { asset = CommsManager.AssetCache.GetAsset(baseItem.AssetID, AssetRequestInfo.InternalRequest()); if (asset == null) return false; // not found } catch { //we couldnt get the asset, cant apply fixups return false; } //do we have the correct asset type to parse? if (asset.Type != (sbyte)AssetType.Clothing && asset.Type != (sbyte)AssetType.Bodypart) return false; try { uint wearableTypeInAsset = this.ParseWearableAndGetType(asset); //do they match? if (wearableTypeInAsset != (baseItem.Flags & 0xFF)) { //no. we need a fixup m_log.ErrorFormat("[APPEARANCE]: Hotpatching item {0} due to flags mismatch: Got {1}, should be {2}", baseItem.ID, baseItem.Flags & 0xFF, wearableTypeInAsset); //remove the first byte baseItem.Flags = baseItem.Flags & 0xFFFFFF00; //combine our type baseItem.Flags = baseItem.Flags | (wearableTypeInAsset & 0xFF); //save back the inventory item with updated flags uinfo.UpdateItem(baseItem); //inform viewer clientView.SendBulkUpdateInventory(baseItem); return true; } return false; } catch (Exception e) { m_log.ErrorFormat("[APPEARANCE]: Error when attempting to parse wearable and update item for Flags hotpatch {0}", e); //couldnt parse wearable return false; } }
private List<SceneObjectGroup> RezMultipleObjectsFromInventory(XmlNodeList nodes, UUID itemId, IClientAPI remoteClient, bool attachment, Vector3 pos, bool RezSelected, InventoryItemBase item, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, Vector3 RayEnd, Vector3 RayStart, byte bRayEndIsIntersection) { Vector3 OldMiddlePos = Vector3.Zero; List<SceneObjectGroup> NewGroup = new List<SceneObjectGroup>(); foreach (System.Xml.XmlNode aPrimNode in nodes) { if (aPrimNode.OuterXml.StartsWith("<middle>")) { string Position = aPrimNode.OuterXml.Remove(0, 13); Position = Position.Remove(Position.Length - 16, 16); string[] XYZ = Position.Split(' '); OldMiddlePos = new Vector3(float.Parse(XYZ[0]), float.Parse(XYZ[1]), float.Parse(XYZ[2])); continue; } SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(aPrimNode.OuterXml, m_Scene); if (group == null) continue; NewGroup.Add(group); string reason; if (!m_Scene.Permissions.CanRezObject( group.ChildrenList.Count, remoteClient.AgentId, pos, out reason) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); return null; } group.ResetIDs(true); if (attachment) { group.RootPart.Flags |= PrimFlags.Phantom; group.RootPart.IsAttachment = true; } if (RezSelected) group.RootPart.AddFlag(PrimFlags.CreateSelected); // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_Scene.AddNewSceneObject(group, true, false); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. if (!attachment) { float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; //group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); } else { group.SetFromItemID(item.ID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); } catch (NullReferenceException) { string isAttachment = ""; if (attachment) isAttachment = " Object was an attachment"; m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + item.ID + " object has no rootpart." + isAttachment); } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List<SceneObjectPart> partList = new List<SceneObjectPart>(group.ChildrenList); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0, UUID.Zero); rootPart.ParentGroup.ResumeScripts(); } if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List<UUID> uuids = new List<UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } } foreach (SceneObjectGroup group in NewGroup) { if (!attachment && OldMiddlePos != Vector3.Zero) { Vector3 NewPosOffset = Vector3.Zero; NewPosOffset.X = group.AbsolutePosition.X - OldMiddlePos.X; NewPosOffset.Y = group.AbsolutePosition.Y - OldMiddlePos.Y; NewPosOffset.Z = group.AbsolutePosition.Z - OldMiddlePos.Z; group.AbsolutePosition = pos + NewPosOffset; } group.ScheduleGroupForFullUpdate(PrimUpdateFlags.FullUpdate); } return NewGroup; }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { // Work out position details byte bRayEndIsIntersection = (byte)0; if (RayEndIsIntersection) { bRayEndIsIntersection = (byte)1; } else { bRayEndIsIntersection = (byte)0; } Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); // Rez object InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); if (item != null) { AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); if (rezAsset != null) { UUID itemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) { itemId = item.ID; } } else { // Brave new fullperm world // itemId = item.ID; } string xmlData = Utils.BytesToString(rezAsset.Data); SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); return null; } group.ResetIDs(); if (attachment) { group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom; group.RootPart.IsAttachment = true; } // For attachments, we must make sure that only a single object update occurs after we've finished // all the necessary operations. m_Scene.AddNewSceneObject(group, true, false); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. if (!attachment) { group.ScheduleGroupForFullUpdate(); float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); } else { group.SetFromItemID(itemID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); } catch (NullReferenceException) { string isAttachment = ""; if (attachment) isAttachment = " Object was an attachment"; m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List<UUID> uuids = new List<UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } return rootPart.ParentGroup; } } return null; }
/// <summary> /// Called by the CopyInventoryFromNotecard caps handler. /// </summary> /// <param name="request"></param> /// <param name="path"></param> /// <param name="param"></param> public string CopyInventoryFromNotecard(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { Hashtable response = new Hashtable(); response["int_response_code"] = 404; response["content_type"] = "text/plain"; response["keepalive"] = false; response["str_response_string"] = ""; try { OSDMap content = (OSDMap)OSDParser.DeserializeLLSDXml(request); UUID objectID = content["object-id"].AsUUID(); UUID notecardID = content["notecard-id"].AsUUID(); UUID folderID = content["folder-id"].AsUUID(); UUID itemID = content["item-id"].AsUUID(); // m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, FolderID:{0}, ItemID:{1}, NotecardID:{2}, ObjectID:{3}", folderID, itemID, notecardID, objectID); if (objectID != UUID.Zero) { SceneObjectPart part = m_Scene.GetSceneObjectPart(objectID); if (part != null) { // TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(notecardID); if (!m_Scene.Permissions.CanCopyObjectInventory(notecardID, objectID, m_HostCapsObj.AgentID)) { return(LLSDHelpers.SerialiseLLSDReply(response)); } } } InventoryItemBase item = null; InventoryItemBase copyItem = null; IClientAPI client = null; m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); item = m_Scene.InventoryService.GetItem(new InventoryItemBase(itemID)); if (item != null) { copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID); if (copyItem != null && client != null) { m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder); client.SendBulkUpdateInventory(copyItem); } } else { m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID); if (client != null) { client.SendAlertMessage("Failed to retrieve item"); } } } catch (Exception e) { m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard : {0}", e.ToString()); } response["int_response_code"] = 200; return(LLSDHelpers.SerialiseLLSDReply(response)); }
private List<ISceneEntity> RezMultipleObjectsFromInventory(XmlNodeList nodes, UUID itemId, IClientAPI remoteClient, Vector3 pos, bool RezSelected, InventoryItemBase item, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, Vector3 RayEnd, Vector3 RayStart, byte bRayEndIsIntersection) { Vector3 OldMiddlePos = Vector3.Zero; List<ISceneEntity> NewGroup = new List<ISceneEntity>(); foreach (XmlNode aPrimNode in nodes) { if (aPrimNode.OuterXml.StartsWith("<middle>")) { string Position = aPrimNode.OuterXml.Remove(0, 13); Position = Position.Remove(Position.Length - 16, 16); string[] XYZ = Position.Split(' '); OldMiddlePos = new Vector3(float.Parse(XYZ[0]), float.Parse(XYZ[1]), float.Parse(XYZ[2])); continue; } ISceneEntity group = SceneEntitySerializer.SceneObjectSerializer.FromOriginalXmlFormat(aPrimNode.OuterXml, m_scene); if (group == null) return null; group.IsDeleted = false; foreach (ISceneChildEntity part in group.ChildrenEntities()) { part.IsLoading = false; } NewGroup.Add(group); string reason; if (!m_scene.Permissions.CanRezObject( group.ChildrenEntities().Count, remoteClient.AgentId, pos, out reason)) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0)) remoteClient.SendBulkUpdateInventory(item); return null; } if (RezSelected) group.RootChild.AddFlag(PrimFlags.CreateSelected); // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_scene.SceneGraph.AddPrimToScene(group); // MainConsole.Instance.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. float offsetHeight = 0; pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; //group.AbsolutePosition = pos; // MainConsole.Instance.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); ISceneChildEntity rootPart = group.GetChildPart(group.UUID); // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. if (NewGroup.Count == 1) { //Only do this to the first object, as it is the only one that will need to be renamed rootPart.Name = item.Name; rootPart.Description = item.Description; } List<ISceneChildEntity> partList = group.ChildrenEntities(); group.SetGroup(remoteClient.ActiveGroupId, remoteClient.AgentId, false); item.Owner = remoteClient.AgentId; if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (ISceneChildEntity part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (ISceneChildEntity part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (group.RootChild.Shape.PCode == (byte) PCode.Prim) group.ClearPartAttachmentData(); // Fire on_rez group.CreateScriptInstances(0, true, StateSource.NewRez, UUID.Zero, false); if (!m_scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // List<UUID> uuids = new List<UUID> {item.ID}; m_scene.InventoryService.DeleteItems(item.Owner, uuids); } } } foreach (ISceneEntity group in NewGroup) { if (OldMiddlePos != Vector3.Zero) { Vector3 NewPosOffset = Vector3.Zero; NewPosOffset.X = group.AbsolutePosition.X - OldMiddlePos.X; NewPosOffset.Y = group.AbsolutePosition.Y - OldMiddlePos.Y; NewPosOffset.Z = group.AbsolutePosition.Z - OldMiddlePos.Z; group.AbsolutePosition = pos + NewPosOffset; } group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); } return NewGroup; }
private UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID, bool isGod) { IUserAccountService userv = m_Scenes[0].UserAccountService; if (userv == null) { return(UUID.Zero); } UserAccount info = userv.GetUserAccount(UUID.Zero, creatorID); if (info == null) { return(UUID.Zero); } IInventoryService inv = m_Scenes[0].InventoryService; if (inv == null) { return(UUID.Zero); } if (folderID == UUID.Zero) { InventoryFolderBase folder = inv.GetFolderForType(userID, AssetType.CallingCard); if (folder == null) // Nowhere to put it { return(UUID.Zero); } folderID = folder.ID; } m_log.DebugFormat("[XCALLINGCARD]: Creating calling card for {0} in inventory of {1}", info.Name, userID); InventoryItemBase item = new InventoryItemBase(); item.AssetID = UUID.Zero; item.AssetType = (int)AssetType.CallingCard; item.BasePermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify); if (isGod) { item.BasePermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Move); } item.EveryOnePermissions = (uint)PermissionMask.None; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify); item.ID = UUID.Random(); item.CreatorId = creatorID.ToString(); item.Owner = userID; item.GroupID = UUID.Zero; item.GroupOwned = false; item.Folder = folderID; item.CreationDate = Util.UnixTimeSinceEpoch(); item.InvType = (int)InventoryType.CallingCard; item.Flags = 0; item.Name = info.Name; item.Description = ""; item.SalePrice = 10; item.SaleType = (byte)SaleType.Not; inv.AddItem(item); IClientAPI client = FindClientObject(userID); if (client != null) { client.SendBulkUpdateInventory(item); } return(item.ID); }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID) { // Work out position details byte bRayEndIsIntersection = (byte)0; if (RayEndIsIntersection) { bRayEndIsIntersection = (byte)1; } else { bRayEndIsIntersection = (byte)0; } Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); System.Xml.XmlDocument doc; InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); SceneObjectGroup group = CreateObjectFromInventory(item, remoteClient, itemID, out doc); if (doc == null) { //No asset, check task inventory IEntity e; m_scene.SceneGraph.TryGetEntity(fromTaskID, out e); if (e != null && e is SceneObjectGroup) { SceneObjectGroup grp = (SceneObjectGroup)e; TaskInventoryItem taskItem = grp.RootPart.Inventory.GetInventoryItem(itemID); item = new InventoryItemBase(); item.ID = UUID.Random(); item.CreatorId = taskItem.CreatorID.ToString(); item.Owner = remoteClient.AgentId; item.AssetID = taskItem.AssetID; item.Description = taskItem.Description; item.Name = taskItem.Name; item.AssetType = taskItem.Type; item.InvType = taskItem.InvType; item.Flags = taskItem.Flags; item.SalePrice = taskItem.SalePrice; item.SaleType = taskItem.SaleType; if (m_scene.Permissions.PropagatePermissions()) { item.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); if (taskItem.InvType == (int)InventoryType.Object) { item.CurrentPermissions = item.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); } else { item.CurrentPermissions = item.BasePermissions & taskItem.CurrentPermissions; } item.CurrentPermissions |= 16; // Slam item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); item.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; } else { item.BasePermissions = taskItem.BasePermissions; item.CurrentPermissions = taskItem.CurrentPermissions; item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions; item.GroupPermissions = taskItem.GroupPermissions; } group = CreateObjectFromInventory(item, remoteClient, itemID, out doc); } else { return(null); } } if (group == null && doc.FirstChild.OuterXml.StartsWith("<groups>")) { List <SceneObjectGroup> Groups = RezMultipleObjectsFromInventory(doc.FirstChild.ChildNodes, itemID, remoteClient, pos, RezSelected, item, RayTargetID, BypassRayCast, RayEndIsIntersection, RayEnd, RayStart, bRayEndIsIntersection); if (Groups.Count != 0) { return(Groups[0]); } else { return(null); } } string reason; if (!m_scene.Permissions.CanRezObject( group.ChildrenList.Count, remoteClient.AgentId, pos, out reason)) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { remoteClient.SendBulkUpdateInventory(item); } remoteClient.SendAlertMessage("You do not have permission to rez objects here."); return(null); } if (RezSelected) { group.RootPart.AddFlag(PrimFlags.CreateSelected); } // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_scene.SceneGraph.AddPrimToScene(group); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // Set it's position in world. float offsetHeight = 0; pos = m_scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); SceneObjectPart rootPart = (SceneObjectPart)group.GetChildPart(group.UUID); if (rootPart == null) { m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart."); return(null); } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart> (group.ChildrenList); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); item.Owner = remoteClient.AgentId; if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, 0, UUID.Zero); rootPart.ParentGroup.ResumeScripts(); group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate); if (!m_scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { List <UUID> uuids = new List <UUID> (); uuids.Add(item.ID); m_scene.InventoryService.DeleteItems(item.Owner, uuids); } } return(group); }
/// <summary> /// Do pre-rez processing when the object comes from an item. /// </summary> /// <param name="remoteClient"></param> /// <param name="item"></param> /// <param name="objlist"></param> /// <param name="pos"></param> /// <param name="veclist"> /// List of vector position adjustments for a coalesced objects. For ordinary objects /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist /// </param> /// <param name="isAttachment"></param> /// <returns>true if we can processed with rezzing, false if we need to abort</returns> private bool DoPreRezWhenFromItem( IClientAPI remoteClient, InventoryItemBase item, List <SceneObjectGroup> objlist, Vector3 pos, List <Vector3> veclist, bool isAttachment) { UUID fromUserInventoryItemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { fromUserInventoryItemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world fromUserInventoryItemId = item.ID; } } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup g = objlist[i]; if (!m_Scene.Permissions.CanRezObject( g.PrimCount, remoteClient.AgentId, pos + veclist[i]) && !isAttachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) { remoteClient.SendBulkUpdateInventory(item); } ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); remoteClient.SendAlertMessage(string.Format( "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name)); return(false); } } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup so = objlist[i]; SceneObjectPart rootPart = so.RootPart; // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } so.FromFolderID = item.Folder; // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", // rootPart.OwnerID, item.Owner, item.CurrentPermissions); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; } foreach (SceneObjectPart part in so.Parts) { part.FromUserInventoryItemID = fromUserInventoryItemId; part.ApplyPermissionsOnRez(item, true, m_Scene); } rootPart.TrimPermissions(); if (isAttachment) { so.FromItemID = item.ID; } } return(true); }
/// <summary> /// Update an item which is either already in the client's inventory or is within /// a transaction /// </summary> /// <param name="remoteClient"></param> /// <param name="transactionID">The transaction ID. If this is UUID.Zero we will /// assume that we are not in a transaction</param> /// <param name="itemID">The ID of the updated item</param> /// <param name="name">The name of the updated item</param> /// <param name="description">The description of the updated item</param> /// <param name="nextOwnerMask">The permissions of the updated item</param> /* public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, UUID itemID, string name, string description, uint nextOwnerMask)*/ public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, UUID itemID, InventoryItemBase itemUpd) { // m_log.DebugFormat( // "[USER INVENTORY]: Updating asset for item {0} {1}, transaction ID {2} for {3}", // itemID, itemUpd.Name, transactionID, remoteClient.Name); // This one will let people set next perms on items in agent // inventory. Rut-Roh. Whatever. Make this secure. Yeah. // // Passing something to another avatar or a an object will already InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); if (item != null) { if (item.Owner != remoteClient.AgentId) return; item.Name = itemUpd.Name; item.Description = itemUpd.Description; // m_log.DebugFormat( // "[USER INVENTORY]: itemUpd {0} {1} {2} {3}, item {4} {5} {6} {7}", // itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, // item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); bool sendUpdate = false; if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid { // Create a set of base permissions that will not include export if the user // is not allowed to change the export flag. bool denyExportChange = false; // m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) denyExportChange = true; // m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange); // If it is already set, force it set and also force full perm // else prevent setting it. It can and should never be set unless // set in base, so the condition above is valid if (denyExportChange) { // If we are not allowed to change it, then force it to the // original item's setting and if it was on, also force full perm if ((item.EveryOnePermissions & (uint)PermissionMask.Export) != 0) { itemUpd.NextPermissions = (uint)(PermissionMask.All); itemUpd.EveryOnePermissions |= (uint)PermissionMask.Export; } else { itemUpd.EveryOnePermissions &= ~(uint)PermissionMask.Export; } } else { // If the new state is exportable, force full perm if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) { // m_log.DebugFormat("[XXX]: Force full perm"); itemUpd.NextPermissions = (uint)(PermissionMask.All); } } if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions; if (item.EveryOnePermissions != (itemUpd.EveryOnePermissions & item.BasePermissions)) item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; item.EveryOnePermissions = itemUpd.EveryOnePermissions & item.BasePermissions; if (item.GroupPermissions != (itemUpd.GroupPermissions & item.BasePermissions)) item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup; item.GroupPermissions = itemUpd.GroupPermissions & item.BasePermissions; item.GroupID = itemUpd.GroupID; item.GroupOwned = itemUpd.GroupOwned; item.CreationDate = itemUpd.CreationDate; // The client sends zero if its newly created? if (itemUpd.CreationDate == 0) item.CreationDate = Util.UnixTimeSinceEpoch(); else item.CreationDate = itemUpd.CreationDate; // TODO: Check if folder changed and move item //item.NextPermissions = itemUpd.Folder; item.InvType = itemUpd.InvType; if (item.SalePrice != itemUpd.SalePrice || item.SaleType != itemUpd.SaleType) item.Flags |= (uint)InventoryItemFlags.ObjectSlamSale; item.SalePrice = itemUpd.SalePrice; item.SaleType = itemUpd.SaleType; if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0) { item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf); sendUpdate = true; } InventoryService.UpdateItem(item); } if (UUID.Zero != transactionID) { if (AgentTransactionsModule != null) { AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); } } else { // This MAY be problematic, if it is, another solution // needs to be found. If inventory item flags are updated // the viewer's notion of the item needs to be refreshed. // // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start // failing frequently. Possibly this is a race with a separate transaction that uploads the asset. if (sendUpdate) remoteClient.SendBulkUpdateInventory(item); } } else { m_log.ErrorFormat( "[AGENTINVENTORY]: Item id {0} not found for an inventory item update for {1}.", itemID, remoteClient.Name); } }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject (IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID) { // Work out position details byte bRayEndIsIntersection = (byte)0; if (RayEndIsIntersection) { bRayEndIsIntersection = (byte)1; } else { bRayEndIsIntersection = (byte)0; } Vector3 scale = new Vector3 (0.5f, 0.5f, 0.5f); Vector3 pos = m_scene.SceneGraph.GetNewRezLocation ( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); System.Xml.XmlDocument doc; InventoryItemBase item = new InventoryItemBase (itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem (item); SceneObjectGroup group = CreateObjectFromInventory (item, remoteClient, itemID, out doc); if (doc == null) { //No asset, check task inventory IEntity e; m_scene.SceneGraph.TryGetEntity (fromTaskID, out e); if (e != null && e is SceneObjectGroup) { SceneObjectGroup grp = (SceneObjectGroup)e; TaskInventoryItem taskItem = grp.RootPart.Inventory.GetInventoryItem (itemID); item = new InventoryItemBase (); item.ID = UUID.Random (); item.CreatorId = taskItem.CreatorID.ToString (); item.Owner = remoteClient.AgentId; item.AssetID = taskItem.AssetID; item.Description = taskItem.Description; item.Name = taskItem.Name; item.AssetType = taskItem.Type; item.InvType = taskItem.InvType; item.Flags = taskItem.Flags; item.SalePrice = taskItem.SalePrice; item.SaleType = taskItem.SaleType; if (m_scene.Permissions.PropagatePermissions ()) { item.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); if (taskItem.InvType == (int)InventoryType.Object) item.CurrentPermissions = item.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); else item.CurrentPermissions = item.BasePermissions & taskItem.CurrentPermissions; item.CurrentPermissions |= 16; // Slam item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); item.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; } else { item.BasePermissions = taskItem.BasePermissions; item.CurrentPermissions = taskItem.CurrentPermissions; item.NextPermissions = taskItem.NextPermissions; item.EveryOnePermissions = taskItem.EveryonePermissions; item.GroupPermissions = taskItem.GroupPermissions; } group = CreateObjectFromInventory (item, remoteClient, itemID, out doc); } else return null; } if (group == null && doc.FirstChild.OuterXml.StartsWith ("<groups>")) { List<SceneObjectGroup> Groups = RezMultipleObjectsFromInventory (doc.FirstChild.ChildNodes, itemID, remoteClient, pos, RezSelected, item, RayTargetID, BypassRayCast, RayEndIsIntersection, RayEnd, RayStart, bRayEndIsIntersection); if (Groups.Count != 0) return Groups[0]; else return null; } string reason; if (!m_scene.Permissions.CanRezObject ( group.ChildrenList.Count, remoteClient.AgentId, pos, out reason)) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) remoteClient.SendBulkUpdateInventory (item); remoteClient.SendAlertMessage ("You do not have permission to rez objects here."); return null; } if (RezSelected) group.RootPart.AddFlag (PrimFlags.CreateSelected); // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_scene.SceneGraph.AddPrimToScene (group); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // Set it's position in world. float offsetHeight = 0; pos = m_scene.SceneGraph.GetNewRezLocation ( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox (out offsetHeight), false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); SceneObjectPart rootPart = (SceneObjectPart)group.GetChildPart (group.UUID); if (rootPart == null) { m_log.Error ("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart."); return null; } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List<SceneObjectPart> partList = new List<SceneObjectPart> (group.ChildrenList); group.SetGroup (remoteClient.ActiveGroupId, remoteClient); item.Owner = remoteClient.AgentId; if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions ()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions (); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner (item.Owner); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions (); if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData (); } // Fire on_rez group.CreateScriptInstances (0, true, 0, UUID.Zero); rootPart.ParentGroup.ResumeScripts (); group.ScheduleGroupUpdate (PrimUpdateFlags.FullUpdate); if (!m_scene.Permissions.BypassPermissions ()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { List<UUID> uuids = new List<UUID> (); uuids.Add (item.ID); m_scene.InventoryService.DeleteItems (item.Owner, uuids); } } return group; }
void OnInstantMessage(IClientAPI client, GridInstantMessage im) { //MainConsole.Instance.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); IScene clientScene = FindClientScene(client.AgentId); if (clientScene == null) // Something seriously wrong here. { MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Cannot find originating user scene"); return; } if (im.Dialog == (byte) InstantMessageDialog.InventoryOffered) { //MainConsole.Instance.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); if (im.BinaryBucket.Length < 17) // Invalid { MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Invalid length {0} for asset type {1}", im.BinaryBucket.Length, ((AssetType)im.BinaryBucket[0])); return; } UUID receipientID = im.ToAgentID; IScenePresence recipientUser = null; IScene recipientUserScene = FindClientScene(client.AgentId); if (recipientUserScene != null) recipientUser = recipientUserScene.GetScenePresence(receipientID); UUID copyID; // user is online now... if (recipientUser != null) { // First byte is the asset type AssetType assetType = (AssetType)im.BinaryBucket [0]; if (assetType == AssetType.Folder) { UUID folderID = new UUID (im.BinaryBucket, 1); MainConsole.Instance.DebugFormat ( "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", folderID, im.ToAgentID); clientScene.InventoryService.GiveInventoryFolderAsync ( receipientID, client.AgentId, folderID, UUID.Zero, (folder) => { if (folder == null) { client.SendAgentAlertMessage ("Can't find folder to give. Nothing given.", false); return; } // The outgoing binary bucket should contain only the byte which signals an asset folder is // being copied and the following bytes for the copied folder's UUID copyID = folder.ID; byte[] copyIDBytes = copyID.GetBytes (); im.BinaryBucket = new byte[ 1 + copyIDBytes.Length ]; im.BinaryBucket [0] = (byte)AssetType.Folder; Array.Copy (copyIDBytes, 0, im.BinaryBucket, 1, copyIDBytes.Length); // m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory folder transfer", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory folder transfer", TransactionType.GiveInventory); if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory (folder); im.SessionID = copyID; recipientUser.ControllingClient.SendInstantMessage (im); } }); } else { // First byte of the array is probably the item type // Next 16 bytes are the UUID UUID itemID = new UUID (im.BinaryBucket, 1); MainConsole.Instance.DebugFormat ( "[INVENTORY TRANSFER]: (giving) Inserting item {0} into agent {1}'s inventory", itemID, im.ToAgentID); clientScene.InventoryService.GiveInventoryItemAsync ( im.ToAgentID, im.FromAgentID, itemID, UUID.Zero, false, (itemCopy) => { if (itemCopy == null) { MainConsole.Instance.DebugFormat ( "[INVENTORY TRANSFER]: (giving) Unable to find item {0} to give to agent {1}'s inventory", itemID, im.ToAgentID); client.SendAgentAlertMessage ("Can't find item to give. Nothing given.", false); return; } copyID = itemCopy.ID; Array.Copy (copyID.GetBytes (), 0, im.BinaryBucket, 1, 16); if (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory item transfer", TransactionType.GiveInventory); if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory (itemCopy); im.SessionID = itemCopy.ID; recipientUser.ControllingClient.SendInstantMessage (im); } }); } } else { // recipient is offline. // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } else if (im.Dialog == (byte) InstantMessageDialog.InventoryAccepted) { IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Acceptance message received"); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } else if (im.Dialog == (byte) InstantMessageDialog.InventoryDeclined) { // Here, the recipient is local and we can assume that the // inventory is loaded. Courtesy of the above bulk update, // It will have been pushed to the client, too // IInventoryService invService = clientScene.InventoryService; MainConsole.Instance.DebugFormat ("[INVENTORY TRANSFER]: Declined message received"); InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, InventoryType.Unknown, FolderType.Trash); UUID inventoryID = im.SessionID; // The inventory item/folder, back from it's trip InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID); InventoryFolderBase folder = null; if (item != null && trashFolder != null) { item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? List<UUID> uuids = new List<UUID> {item.ID}; invService.DeleteItems(item.Owner, uuids); ILLClientInventory inventory = client.Scene.RequestModuleInterface<ILLClientInventory>(); if (inventory != null) inventory.AddInventoryItemAsync(client, item); } else { folder = new InventoryFolderBase(inventoryID, client.AgentId); folder = invService.GetFolder(folder); if (folder != null & trashFolder != null) { folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); } } if ((null == item && null == folder) | null == trashFolder) { string reason = String.Empty; if (trashFolder == null) reason += " Trash folder not found."; if (item == null) reason += " Item not found."; if (folder == null) reason += " Folder not found."; client.SendAgentAlertMessage("Unable to delete " + "received inventory" + reason, false); } //m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory transfer declined", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory transfer declined", TransactionType.GiveInventory); IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) m_TransferModule.SendInstantMessage(im); } } }
/// <summary> /// Rez an object into the scene from the user's inventory /// </summary> /// FIXME: It would be really nice if inventory access modules didn't also actually do the work of rezzing /// things to the scene. The caller should be doing that, I think. /// <param name="remoteClient"></param> /// <param name="itemID"></param> /// <param name="RayEnd"></param> /// <param name="RayStart"></param> /// <param name="RayTargetID"></param> /// <param name="BypassRayCast"></param> /// <param name="RayEndIsIntersection"></param> /// <param name="RezSelected"></param> /// <param name="RemoveItem"></param> /// <param name="fromTaskID"></param> /// <param name="attachment"></param> /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) { // Work out position details byte bRayEndIsIntersection = (byte)0; if (RayEndIsIntersection) { bRayEndIsIntersection = (byte)1; } else { bRayEndIsIntersection = (byte)0; } Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); Vector3 pos = m_Scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, scale, false); // Rez object InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); if (item != null) { AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); if (rezAsset != null) { UUID itemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) { itemId = item.ID; } } else { // Brave new fullperm world // itemId = item.ID; } string xmlData = Utils.BytesToString(rezAsset.Data); System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.LoadXml(xmlData); System.Xml.XmlNode rootNode = doc.FirstChild; if (doc.FirstChild.OuterXml.StartsWith("<groups>")) { List<SceneObjectGroup> Groups = RezMultipleObjectsFromInventory(rootNode.ChildNodes, itemId, remoteClient, attachment, pos, RezSelected, item, RayTargetID, BypassRayCast, RayEndIsIntersection, RayEnd, RayStart, bRayEndIsIntersection); if (Groups.Count != 0) return Groups[0]; else return null; } SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, doc.FirstChild.OuterXml, m_Scene); if (group == null) return null; group.IsDeleted = false; group.m_isLoaded = true; foreach (SceneObjectPart part in group.ChildrenList) { part.IsLoading = false; } string reason; if (!m_Scene.Permissions.CanRezObject( group.ChildrenList.Count, remoteClient.AgentId, pos, out reason) && !attachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment)) remoteClient.SendBulkUpdateInventory(item); remoteClient.SendAlertMessage("You do not have permission to rez objects here."); return null; } if (attachment) { group.RootPart.Flags |= PrimFlags.Phantom; group.RootPart.IsAttachment = true; } if (RezSelected) group.RootPart.AddFlag(PrimFlags.CreateSelected); // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than one full update during the attachment // process causes some clients to fail to display the attachment properly. m_Scene.SceneGraph.AddPrimToScene(group); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that // if not, we set it's position in world. if (!attachment) { float offsetHeight = 0; pos = m_Scene.SceneGraph.GetNewRezLocation( RayStart, RayEnd, RayTargetID, Quaternion.Identity, BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); pos.Z += offsetHeight; group.AbsolutePosition = pos; // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); } else { group.SetFromItemID(itemID); } SceneObjectPart rootPart = null; try { rootPart = group.GetChildPart(group.UUID); if (rootPart == null) { //Just throw the null rootPart.Acceleration = new Vector3(); } } catch (NullReferenceException) { string isAttachment = ""; if (attachment) isAttachment = " Object was an attachment"; m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); return null; } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. rootPart.Name = item.Name; rootPart.Description = item.Description; List<SceneObjectPart> partList = new List<SceneObjectPart>(group.ChildrenList); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (rootPart.OwnerID != item.Owner) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { if ((item.CurrentPermissions & 8) != 0) { foreach (SceneObjectPart part in partList) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } group.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; part.GroupMask = 0; // DO NOT propagate here } } rootPart.TrimPermissions(); if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { group.ClearPartAttachmentData(); } // Fire on_rez group.CreateScriptInstances(0, true, 0, UUID.Zero); rootPart.ParentGroup.ResumeScripts(); } group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate); if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { // If this is done on attachments, no // copy ones will be lost, so avoid it // if (!attachment) { List<UUID> uuids = new List<UUID>(); uuids.Add(item.ID); m_Scene.InventoryService.DeleteItems(item.Owner, uuids); } } } return group; } } return null; }
private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { //MainConsole.Instance.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); IScene clientScene = FindClientScene(client.AgentId); if (clientScene == null) // Something seriously wrong here. { MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Cannot find originating user scene"); return; } if (im.Dialog == (byte)InstantMessageDialog.InventoryOffered) { //MainConsole.Instance.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); if (im.BinaryBucket.Length < 17) // Invalid { MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Invalid length {0} for asset type {1}", im.BinaryBucket.Length, ((AssetType)im.BinaryBucket[0])); return; } UUID receipientID = im.ToAgentID; IScenePresence recipientUser = null; IScene recipientUserScene = FindClientScene(client.AgentId); if (recipientUserScene != null) { recipientUser = recipientUserScene.GetScenePresence(receipientID); } UUID copyID; // user is online now... if (recipientUser != null) { // First byte is the asset type AssetType assetType = (AssetType)im.BinaryBucket [0]; if (assetType == AssetType.Folder) { UUID folderID = new UUID(im.BinaryBucket, 1); MainConsole.Instance.DebugFormat( "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", folderID, im.ToAgentID); clientScene.InventoryService.GiveInventoryFolderAsync( receipientID, client.AgentId, folderID, UUID.Zero, (folder) => { if (folder == null) { client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); return; } // The outgoing binary bucket should contain only the byte which signals an asset folder is // being copied and the following bytes for the copied folder's UUID copyID = folder.ID; byte[] copyIDBytes = copyID.GetBytes(); im.BinaryBucket = new byte[1 + copyIDBytes.Length]; im.BinaryBucket [0] = (byte)AssetType.Folder; Array.Copy(copyIDBytes, 0, im.BinaryBucket, 1, copyIDBytes.Length); // m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory folder transfer", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) { moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory folder transfer", TransactionType.GiveInventory); } if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory(folder); im.SessionID = copyID; recipientUser.ControllingClient.SendInstantMessage(im); } }); } else { // First byte of the array is probably the item type // Next 16 bytes are the UUID UUID itemID = new UUID(im.BinaryBucket, 1); MainConsole.Instance.DebugFormat( "[INVENTORY TRANSFER]: (giving) Inserting item {0} into agent {1}'s inventory", itemID, im.ToAgentID); clientScene.InventoryService.GiveInventoryItemAsync( im.ToAgentID, im.FromAgentID, itemID, UUID.Zero, false, (itemCopy) => { if (itemCopy == null) { MainConsole.Instance.DebugFormat( "[INVENTORY TRANSFER]: (giving) Unable to find item {0} to give to agent {1}'s inventory", itemID, im.ToAgentID); client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); return; } copyID = itemCopy.ID; Array.Copy(copyID.GetBytes(), 0, im.BinaryBucket, 1, 16); if (moneyService != null) { moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory item transfer", TransactionType.GiveInventory); } if (recipientUser != null) { recipientUser.ControllingClient.SendBulkUpdateInventory(itemCopy); im.SessionID = itemCopy.ID; recipientUser.ControllingClient.SendInstantMessage(im); } }); } } else { // recipient is offline. // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im); } } } else if (im.Dialog == (byte)InstantMessageDialog.InventoryAccepted) { IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Acceptance message received"); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im); } } } else if (im.Dialog == (byte)InstantMessageDialog.InventoryDeclined) { // Here, the recipient is local and we can assume that the // inventory is loaded. Courtesy of the above bulk update, // It will have been pushed to the client, too // IInventoryService invService = clientScene.InventoryService; MainConsole.Instance.DebugFormat("[INVENTORY TRANSFER]: Declined message received"); InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, InventoryType.Unknown, AssetType.TrashFolder); UUID inventoryID = im.SessionID; // The inventory item/folder, back from it's trip InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID); InventoryFolderBase folder = null; if (item != null && trashFolder != null) { item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? List <UUID> uuids = new List <UUID> { item.ID }; invService.DeleteItems(item.Owner, uuids); ILLClientInventory inventory = client.Scene.RequestModuleInterface <ILLClientInventory>(); if (inventory != null) { inventory.AddInventoryItemAsync(client, item); } } else { folder = new InventoryFolderBase(inventoryID, client.AgentId); folder = invService.GetFolder(folder); if (folder != null & trashFolder != null) { folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); } } if ((null == item && null == folder) | null == trashFolder) { string reason = String.Empty; if (trashFolder == null) { reason += " Trash folder not found."; } if (item == null) { reason += " Item not found."; } if (folder == null) { reason += " Folder not found."; } client.SendAgentAlertMessage("Unable to delete " + "received inventory" + reason, false); } //m_currencyService.UserCurrencyTransfer(im.FromAgentID, im.ToAgentID, 0, // "Inworld inventory transfer declined", TransactionType.GiveInventory, UUID.Zero); if (moneyService != null) { moneyService.Transfer(im.ToAgentID, im.FromAgentID, 0, "Inworld inventory transfer declined", TransactionType.GiveInventory); } IScenePresence user = clientScene.GetScenePresence(im.ToAgentID); if (user != null) // Local { user.ControllingClient.SendInstantMessage(im); } else { if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im); } } } }
/// <summary> /// Do pre-rez processing when the object comes from an item. /// </summary> /// <param name="remoteClient"></param> /// <param name="item"></param> /// <param name="objlist"></param> /// <param name="pos"></param> /// <param name="isAttachment"></param> /// <returns>true if we can processed with rezzing, false if we need to abort</returns> private bool DoPreRezWhenFromItem( IClientAPI remoteClient, InventoryItemBase item, List <SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) { UUID fromUserInventoryItemId = UUID.Zero; // If we have permission to copy then link the rezzed object back to the user inventory // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { fromUserInventoryItemId = item.ID; } } else { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { // Brave new fullperm world fromUserInventoryItemId = item.ID; } } int primcount = 0; foreach (SceneObjectGroup g in objlist) { primcount += g.PrimCount; } if (!m_Scene.Permissions.CanRezObject( primcount, remoteClient.AgentId, pos) && !isAttachment) { // The client operates in no fail mode. It will // have already removed the item from the folder // if it's no copy. // Put it back if it's not an attachment // if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) { remoteClient.SendBulkUpdateInventory(item); } return(false); } for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup so = objlist[i]; SceneObjectPart rootPart = so.RootPart; // Since renaming the item in the inventory does not // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. // // Only do these for the first object if we are rezzing a coalescence. if (i == 0) { rootPart.Name = item.Name; rootPart.Description = item.Description; rootPart.ObjectSaleType = item.SaleType; rootPart.SalePrice = item.SalePrice; } rootPart.FromFolderID = item.Folder; // Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", // rootPart.OwnerID, item.Owner, item.CurrentPermissions); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; rootPart.SalePrice = 10; if (m_Scene.Permissions.PropagatePermissions()) { foreach (SceneObjectPart part in so.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } part.GroupMask = 0; // DO NOT propagate here } so.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in so.Parts) { part.FromUserInventoryItemID = fromUserInventoryItemId; if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.Inventory.ChangeInventoryOwner(item.Owner); part.GroupMask = 0; // DO NOT propagate here } part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); if (isAttachment) { so.SetFromItemID(item.ID); } } return(true); }