protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { SceneObjectGroup objatt = invAccess.RezObject(remoteClient, itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, remoteClient.AgentId, true); // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", // objatt.Name, remoteClient.Name, AttachmentPt); if (objatt != null) { bool tainted = false; if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) { tainted = true; } // This will throw if the attachment fails try { AttachObject(remoteClient, objatt, AttachmentPt, false); } catch { // Make sure the object doesn't stick around and bail m_scene.DeleteSceneObject(objatt, false); return(null); } if (tainted) { objatt.HasGroupChanged = true; } // Fire after attach, so we don't get messy perms dialogs // 4 == AttachedRez objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); objatt.ResumeScripts(); // Do this last so that event listeners have access to all the effects of the attachment m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); } else { m_log.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, remoteClient.Name, AttachmentPt); } return(objatt); } return(null); }
/// <summary> /// Move the next object in the queue to inventory. Then delete it properly from the scene. /// </summary> /// <returns></returns> public bool InventoryDeQueueAndDelete() { DeleteToInventoryHolder x = null; try { lock (m_inventoryDeletes) { int left = m_inventoryDeletes.Count; if (left > 0) { x = m_inventoryDeletes.Dequeue(); // m_log.DebugFormat( // "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", // left, x.action, x.objectGroups.Count); try { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false); } if (x.permissionToDelete) { foreach (SceneObjectGroup g in x.objectGroups) { m_scene.DeleteSceneObject(g, true); } } } catch (Exception e) { m_log.ErrorFormat( "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); } return(true); } } } catch (Exception e) { // We can't put the object group details in here since the root part may have disappeared (which is where these sit). // FIXME: This needs to be fixed. m_log.ErrorFormat( "[ASYNC DELETER]: Queued sending of scene object to agent {0} {1} failed: {2} {3}", (x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.Message, e.StackTrace); } // m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue."); return(false); }
public bool DeleteObject() { DeleteToInventoryHolder x = null; try { if (m_removeFromSimQueue.TryDequeue(out x)) { MainConsole.Instance.DebugFormat( "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", m_removeFromSimQueue.Count); if (x.permissionToTake) { try { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); UUID itemID; if (invAccess != null) { invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.agentId, out itemID); } } catch (Exception e) { MainConsole.Instance.ErrorFormat( "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); } } //Moved Delete To After Object Taken To Inventory. Prevents script variables not being updated before taken to inventory if (x.permissionToDelete) { IBackupModule backup = m_scene.RequestModuleInterface <IBackupModule>(); if (backup != null) { backup.DeleteSceneObjects(x.objectGroups.ToArray(), true, true); } } return(true); } } catch (Exception e) { // We can't put the object group details in here since the root part may have disappeared (which is where these sit). // FIXME: This needs to be fixed. MainConsole.Instance.ErrorFormat( "[SCENE]: Queued sending of scene object to agent {0} {1} failed: {2}", (x != null ? x.agentId.ToString() : "unavailable"), (x != null ? x.agentId.ToString() : "unavailable"), e); } //MainConsole.Instance.Debug("[SCENE]: No objects left in delete queue."); return(false); }
/// <summary> /// Move the next object in the queue to inventory. Then delete it properly from the scene. /// </summary> /// <returns></returns> public void InventoryDeQueueAndDelete() { lock (m_threadLock) { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess == null) { return; } int count = 0; while (m_inventoryDeletes.TryDequeue(out DeleteToInventoryHolder x)) { // m_log.DebugFormat( // "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", // left, x.action, x.objectGroups.Count); try { invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false); if (x.permissionToDelete) { foreach (SceneObjectGroup g in x.objectGroups) { m_scene.DeleteSceneObject(g, true); } } count += x.objectGroups.Count; if (count > 256) { Thread.Sleep(50); // throttle count = 0; } } catch // catch (Exception e) { //m_log.ErrorFormat( // "[ASYNC OBJECT DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); } } // m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue."); m_running = false; } }
public void RegionLoaded(Scene scene) { m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>(); }
private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { lock (sp.AttachmentsSyncLock) { SceneObjectGroup objatt; if (itemID != UUID.Zero) { objatt = invAccess.RezObject(sp.ControllingClient, itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, sp.UUID, true); } else { objatt = invAccess.RezObject(sp.ControllingClient, null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, sp.UUID, true); } // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", // objatt.Name, remoteClient.Name, AttachmentPt); if (objatt != null) { // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. objatt.HasGroupChanged = false; bool tainted = false; if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) { tainted = true; } // This will throw if the attachment fails try { AttachObject(sp, objatt, attachmentPt, false); } catch (Exception e) { m_log.ErrorFormat( "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); // Make sure the object doesn't stick around and bail sp.RemoveAttachment(objatt); m_scene.DeleteSceneObject(objatt, false); return(null); } if (tainted) { objatt.HasGroupChanged = true; } // Fire after attach, so we don't get messy perms dialogs // 4 == AttachedRez objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); objatt.ResumeScripts(); // Do this last so that event listeners have access to all the effects of the attachment m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); return(objatt); } else { m_log.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, sp.Name, attachmentPt); } } } return(null); }
/// <summary> /// Attach the object to the avatar /// </summary> /// <param name="remoteClient">The client that is having the attachment done</param> /// <param name="localID">The localID (SceneObjectPart) that is being attached (for the attach script event)</param> /// <param name="group">The group (SceneObjectGroup) that is being attached</param> /// <param name="AttachmentPt">The point to where the attachment will go</param> /// <param name="assetID" /> /// <param name="forceUpdatePrim">Force updating of the prim the next time the user attempts to deattach it</param> /// <param name="isTempAttach">Is a temporary attachment</param> protected void FindAttachmentPoint(IClientAPI remoteClient, uint localID, ISceneEntity group, int AttachmentPt, UUID assetID, bool forceUpdatePrim, bool isTempAttach) { //Make sure that we arn't over the limit of attachments ISceneEntity[] attachments = GetAttachmentsForAvatar(remoteClient.AgentId); if (attachments.Length + 1 > m_maxNumberOfAttachments) { //Too many remoteClient.SendAgentAlertMessage( "You are wearing too many attachments. Take one off to attach this object", false); return; } Vector3 attachPos = group.GetAttachmentPos(); bool hasMultipleAttachmentsSet = (AttachmentPt & 0x7f) != 0 || AttachmentPt == 0; if (!m_allowMultipleAttachments) { hasMultipleAttachmentsSet = false; } AttachmentPt &= 0x7f; //Disable it! Its evil! //Did the attachment change position or attachment point? bool changedPositionPoint = false; // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. //Simplier terms: the attachment point changed, set it to the default 0,0,0 location if (AttachmentPt != 0 && AttachmentPt != (group.GetAttachmentPoint() & 0x7f)) { attachPos = Vector3.Zero; changedPositionPoint = true; } else { // AttachmentPt 0 means the client chose to 'wear' the attachment. if (AttachmentPt == 0) { // Check object for stored attachment point AttachmentPt = group.GetSavedAttachmentPoint() & 0x7f; attachPos = group.GetAttachmentPos(); } //Check state afterwards... use the newer GetSavedAttachmentPoint and Pos above first if (AttachmentPt == 0) { // Check object for older stored attachment point AttachmentPt = group.RootChild.Shape.State & 0x7f; } // if we still didn't find a suitable attachment point, force it to the default //This happens on the first time an avatar 'wears' an object if (AttachmentPt == 0) { // Stick it on right hand with Zero Offset from the attachment point. AttachmentPt = (int)AttachmentPoint.RightHand; //Default location attachPos = Vector3.Zero; changedPositionPoint = true; } } MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2} localID {3}", group.Name, remoteClient.Name, AttachmentPt, group.LocalId); //Update where we are put group.SetAttachmentPoint((byte)AttachmentPt); //Fix the position with the one we found group.AbsolutePosition = attachPos; // Remove any previous attachments IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence == null) { return; } UUID itemID = UUID.Zero; //Check for multiple attachment bits and whether we should remove the old if (!hasMultipleAttachmentsSet) { foreach (ISceneEntity grp in attachments) { if (grp.GetAttachmentPoint() == (byte)AttachmentPt) { itemID = grp.RootChild.FromUserInventoryItemID; break; } } if (itemID != UUID.Zero) { DetachSingleAttachmentToInventory(itemID, remoteClient); } } itemID = group.RootChild.FromUserInventoryItemID; group.RootChild.AttachedAvatar = presence.UUID; List <ISceneChildEntity> parts = group.ChildrenEntities(); foreach (ISceneChildEntity t in parts) { t.AttachedAvatar = presence.UUID; } if (group.RootChild.PhysActor != null) { m_scene.PhysicsScene.DeletePrim(group.RootChild.PhysActor); group.RootChild.PhysActor = null; } group.RootChild.AttachedPos = attachPos; group.RootChild.IsAttachment = true; group.AbsolutePosition = attachPos; group.RootChild.SetParentLocalId(presence.LocalId); group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); // Killing it here will cause the client to deselect it // It then reappears on the avatar, deselected // through the full update below if (group.IsSelected) { foreach (ISceneChildEntity part in group.ChildrenEntities()) { part.CreateSelected = true; } } //NOTE: This MUST be here, otherwise we limit full updates during attachments when they are selected and it will block the first update. // So until that is changed, this MUST stay. The client will instantly reselect it, so this value doesn't stay borked for long. group.IsSelected = false; if (!isTempAttach) { if (itemID == UUID.Zero) { //Delete the object inworld to inventory List <ISceneEntity> groups = new List <ISceneEntity>(1) { group }; IInventoryAccessModule inventoryAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (inventoryAccess != null) { inventoryAccess.DeleteToInventory(DeRezAction.AcquireToUserInventory, UUID.Zero, groups, remoteClient.AgentId, out itemID); } } else { //it came from an item, we need to start the scripts // Fire after attach, so we don't get messy perms dialogs. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); } if (UUID.Zero == itemID) { MainConsole.Instance.Error( "[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID."); remoteClient.SendAgentAlertMessage( "Unable to save attachment. Error inventory item ID.", false); return; } // XXYY!! if (assetID == UUID.Zero) { assetID = m_scene.InventoryService.GetItemAssetID(remoteClient.AgentId, itemID); //Update the ItemID with the new item group.SetFromItemID(itemID, assetID); } } else { // Fire after attach, so we don't get messy perms dialogs. group.CreateScriptInstances(0, true, StateSource.AttachedRez, UUID.Zero, false); group.RootChild.FromUserInventoryItemID = UUID.Zero; } AvatarAttachments attPlugin = presence.RequestModuleInterface <AvatarAttachments>(); if (attPlugin != null) { attPlugin.AddAttachment(group); presence.SetAttachments(attPlugin.Get()); if (!isTempAttach) { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); appearance.Appearance.SetAttachments(attPlugin.Get()); AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); } } // In case it is later dropped again, don't let // it get cleaned up group.RootChild.RemFlag(PrimFlags.TemporaryOnRez); group.HasGroupChanged = changedPositionPoint || forceUpdatePrim; //Now recreate it so that it is selected group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); m_scene.EventManager.TriggerOnAttach(localID, group.RootChild.FromUserInventoryItemID, remoteClient.AgentId); }
public ISceneEntity RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, UUID assetID, int AttachmentPt, bool updateUUIDs) { MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { InventoryItemBase item = null; ISceneEntity objatt = assetID == UUID.Zero ? invAccess.CreateObjectFromInventory(remoteClient, itemID, out item) : invAccess.CreateObjectFromInventory(remoteClient, itemID, assetID, null); if (objatt != null) { #region Set up object for attachment status if (item != null) { assetID = item.AssetID; // 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. objatt.RootChild.Name = item.Name; objatt.RootChild.Description = item.Description; } objatt.RootChild.Flags |= PrimFlags.Phantom; objatt.RootChild.IsAttachment = true; objatt.SetFromItemID(itemID, assetID); List <ISceneChildEntity> partList = new List <ISceneChildEntity>(objatt.ChildrenEntities()); foreach (ISceneChildEntity part in partList) { part.AttachedAvatar = remoteClient.AgentId; } objatt.SetGroup(remoteClient.ActiveGroupId, remoteClient.AgentId, false); if (objatt.RootChild.OwnerID != remoteClient.AgentId) { //Need to kill the for sale here objatt.RootChild.ObjectSaleType = 0; objatt.RootChild.SalePrice = 10; if (m_scene.Permissions.PropagatePermissions()) { if (item == null) { item = m_scene.InventoryService.GetItem(remoteClient.AgentId, itemID); } if (item == null) { return(null); } 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 } } objatt.ApplyNextOwnerPermissions(); } } foreach (ISceneChildEntity part in partList) { if (part.OwnerID != remoteClient.AgentId) { part.LastOwnerID = part.OwnerID; part.OwnerID = remoteClient.AgentId; part.Inventory.ChangeInventoryOwner(remoteClient.AgentId); } } objatt.RootChild.TrimPermissions(); objatt.RootChild.IsAttachment = true; objatt.IsDeleted = false; //Update the ItemID with the new item objatt.SetFromItemID(itemID, assetID); //We also have to reset the IDs so that it doesn't have the same IDs as one inworld (possibly)! ISceneEntity[] atts = GetAttachmentsForAvatar(remoteClient.AgentId); foreach (var obj in atts) { if (obj.UUID == objatt.UUID) { updateUUIDs = false; //If the user is already wearing it, don't readd } } bool forceUpdateOnNextDeattach = false; try { bool foundDuplicate = false; foreach (var obj in atts) { if (obj.RootChild.FromUserInventoryItemID == objatt.RootChild.FromUserInventoryItemID) { foundDuplicate = true; } } IEntity e; if (!m_scene.SceneGraph.TryGetEntity(objatt.UUID, out e)) //if (updateUUIDs) { foreach (var prim in objatt.ChildrenEntities()) { prim.LocalId = 0; } bool success = m_scene.SceneGraph.RestorePrimToScene(objatt, false); if (!success) { MainConsole.Instance.Error("[AttachmentModule]: Failed to add attachment " + objatt.Name + " for user " + remoteClient.Name + "!"); return(null); } } else { if (!foundDuplicate) { //If the user has information stored about this object, we need to force updating next time if (m_scene.SceneGraph.AddPrimToScene(objatt)) { forceUpdateOnNextDeattach = true; } } else { if (e as ISceneEntity != null) { (e as ISceneEntity).ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate); } return(e as ISceneEntity); //It was already added } } } catch { } //If we updated the attachment, we need to save the change IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence != null) { FindAttachmentPoint(remoteClient, objatt.LocalId, objatt, AttachmentPt, assetID, forceUpdateOnNextDeattach, false); } else { objatt = null; //Presence left, kill the attachment } #endregion } else { MainConsole.Instance.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, remoteClient.Name, AttachmentPt); } return(objatt); } return(null); }
public void RegionLoaded(Scene scene) { m_invAccessModule = m_scene.RequestModuleInterface <IInventoryAccessModule>(); }
public ISceneEntity RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, int AttachmentPt) { m_log.DebugFormat( "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { SceneObjectGroup objatt = invAccess.CreateObjectFromInventory(remoteClient, itemID); if (objatt != null) { #region Set up object for attachment status InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); objatt.RootPart.Flags |= PrimFlags.Phantom; objatt.RootPart.IsAttachment = true; objatt.SetFromItemID(itemID); // 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. objatt.RootPart.Name = item.Name; objatt.RootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart>(objatt.ChildrenList); objatt.SetGroup(remoteClient.ActiveGroupId, remoteClient); if (objatt.RootPart.OwnerID != item.Owner) { //Need to kill the for sale here objatt.RootPart.ObjectSaleType = 0; objatt.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 } } objatt.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } } objatt.RootPart.TrimPermissions(); objatt.RootPart.IsAttachment = true; objatt.IsDeleted = false; //NOTE: we MUST do this manually, otherwise it will never be added! //We also have to reset the IDs! //Note: root first, as we have to set the parentID right! m_scene.SceneGraph.PrepPrimForAdditionToScene(objatt); m_scene.Entities.Add(objatt); #endregion // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", // objatt.Name, remoteClient.Name, AttachmentPt); FindAttachmentPoint(remoteClient, objatt.LocalId, objatt, AttachmentPt, item); } else { m_log.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, remoteClient.Name, AttachmentPt); } return(objatt); } return(null); }
public ISceneEntity RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, int AttachmentPt) { MainConsole.Instance.DebugFormat( "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface <IInventoryAccessModule>(); if (invAccess != null) { SceneObjectGroup objatt = invAccess.CreateObjectFromInventory(remoteClient, itemID); if (objatt != null) { #region Set up object for attachment status InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_scene.InventoryService.GetItem(item); if (item == null) { return(null); } objatt.RootPart.Flags |= PrimFlags.Phantom; objatt.RootPart.IsAttachment = true; objatt.SetFromItemID(itemID, item.AssetID); // 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. objatt.RootPart.Name = item.Name; objatt.RootPart.Description = item.Description; List <SceneObjectPart> partList = new List <SceneObjectPart>(objatt.ChildrenList); foreach (SceneObjectPart part in partList) { part.AttachedAvatar = remoteClient.AgentId; } objatt.SetGroup(remoteClient.ActiveGroupId, remoteClient.AgentId); if (objatt.RootPart.OwnerID != item.Owner) { //Need to kill the for sale here objatt.RootPart.ObjectSaleType = 0; objatt.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 } } objatt.ApplyNextOwnerPermissions(); } } foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); } } objatt.RootPart.TrimPermissions(); objatt.RootPart.IsAttachment = true; objatt.IsDeleted = false; //Update the ItemID with the new item objatt.SetFromItemID(itemID, item.AssetID); //DO NOT SEND THIS KILL ENTITY // If we send this, when someone copies an inworld object, then wears it, the inworld objects disapepars // If a bug is caused by this, we need to figure out some other workaround. //SendKillEntity(objatt.RootChild); //We also have to reset the IDs so that it doesn't have the same IDs as one inworld (possibly)! m_scene.SceneGraph.PrepPrimForAdditionToScene(objatt); m_scene.Entities.Add(objatt); //If we updated the attachment, we need to save the change IScenePresence presence = m_scene.GetScenePresence(remoteClient.AgentId); if (presence != null) { IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>(); AvatarAttachments attPlugin = presence.RequestModuleInterface <AvatarAttachments>(); bool save = appearance.Appearance.CheckWhetherAttachmentChanged(AttachmentPt, item.ID, item.AssetID); attPlugin.AddAttachment(objatt); appearance.Appearance.SetAttachments(attPlugin.Get()); if (save) { AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); } MainConsole.Instance.InfoFormat( "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2} localID {3}", objatt.Name, remoteClient.Name, AttachmentPt, objatt.LocalId); FindAttachmentPoint(remoteClient, objatt.LocalId, objatt, AttachmentPt, item); } else { objatt = null;//Presence left, kill the attachment } #endregion } else { MainConsole.Instance.WarnFormat( "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", itemID, remoteClient.Name, AttachmentPt); } return(objatt); } return(null); }