From fe4c3a37c0a4d41c410ef99003c7ab437bdbc5f0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Aug 2012 00:12:15 +0100 Subject: [PATCH 1/5] Lay some groundwork for temp attachments. Decouple attachments from inventory. --- .../Avatar/Attachments/AttachmentsModule.cs | 41 ++++++++++++------- .../Tests/AttachmentsModuleTests.cs | 6 +-- .../Interfaces/IAttachmentsModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 464dfd34e0..77dd0f0c2f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -239,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments sp.ClearAttachments(); } - public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) + public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) { lock (sp.AttachmentsSyncLock) { @@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.AbsolutePosition = attachPos; if (sp.PresenceType != PresenceType.Npc) - UpdateUserInventoryWithAttachment(sp, group, attachmentPt); + UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); AttachToAgent(sp, group, attachmentPt, attachPos, silent); } @@ -306,7 +306,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } - private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) + private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp) { // Remove any previous attachments List attachments = sp.GetAttachments(attachmentPt); @@ -316,18 +316,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { if (attachments[0].FromItemID != UUID.Zero) DetachSingleAttachmentToInvInternal(sp, attachments[0]); - else - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", - attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); + // Error logging commented because UUID.Zero now means temp attachment +// else +// m_log.WarnFormat( +// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", +// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); } // Add the new attachment to inventory if we don't already have it. - UUID newAttachmentItemID = group.FromItemID; - if (newAttachmentItemID == UUID.Zero) - newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; + if (!temp) + { + UUID newAttachmentItemID = group.FromItemID; + if (newAttachmentItemID == UUID.Zero) + newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; - ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); + ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); + } } public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) @@ -416,7 +420,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.PrimCount, sp.UUID, sp.AbsolutePosition)) return; - bool changed = sp.Appearance.DetachAttachment(inventoryID); + bool changed = false; + if (inventoryID != UUID.Zero) + changed = sp.Appearance.DetachAttachment(inventoryID); if (changed && m_scene.AvatarFactory != null) m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); @@ -521,6 +527,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) { + if (grp.FromItemID == UUID.Zero) + { + // We can't save temp attachments + grp.HasGroupChanged = false; + return; + } + // Saving attachments for NPCs messes them up for the real owner! INPCModule module = m_scene.RequestModuleInterface(); if (module != null) @@ -777,7 +790,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This will throw if the attachment fails try { - AttachObject(sp, objatt, attachmentPt, false); + AttachObject(sp, objatt, attachmentPt, false, false); } catch (Exception e) { @@ -931,7 +944,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments AttachmentPt &= 0x7f; // Calls attach with a Zero position - if (AttachObject(sp, part.ParentGroup, AttachmentPt, false)) + if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false)) { // m_log.Debug( // "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 6e7a414df1..1d13f753f6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -189,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false); + scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); // Check status on scene presence Assert.That(sp.HasAttachments(), Is.True); @@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests sp2.AbsolutePosition = new Vector3(0, 0, 0); sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false); + scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); Assert.That(sp.HasAttachments(), Is.False); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); @@ -641,4 +641,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); // } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index d5200b73ed..8155eabbbe 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// true if the object was successfully attached, false otherwise - bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent); + bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool temp); /// /// Rez an attachment from user inventory and change inventory status to match. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 40cfb72bd7..0967c3427e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2628,7 +2628,7 @@ namespace OpenSim.Region.Framework.Scenes RootPrim.RemFlag(PrimFlags.TemporaryOnRez); if (AttachmentsModule != null) - AttachmentsModule.AttachObject(sp, grp, 0, false); + AttachmentsModule.AttachObject(sp, grp, 0, false, false); } else { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e87ec1c4a5..1287709f4d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3043,7 +3043,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; if (attachmentsModule != null) - return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false); + return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); else return false; } From 50db8649aaf4b80d8af33c9f14a5b58122dee88f Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Aug 2012 00:29:39 +0100 Subject: [PATCH 2/5] Exclude temp attachemnts from being sent to the avatar service --- OpenSim/Services/Interfaces/IAvatarService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs index cda7113a4f..863fd93746 100644 --- a/OpenSim/Services/Interfaces/IAvatarService.cs +++ b/OpenSim/Services/Interfaces/IAvatarService.cs @@ -176,7 +176,8 @@ namespace OpenSim.Services.Interfaces List attachments = appearance.GetAttachments(); foreach (AvatarAttachment attach in attachments) { - Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); + if (attach.ItemID != UUID.Zero) + Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); } } From 62acfabec4638284e0d9c88ccbd50d2d0f4b65a6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Aug 2012 00:54:12 +0100 Subject: [PATCH 3/5] Add the skeleton for the temp attachments module --- .../Attachments/TempAttachmentsModule.cs | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs new file mode 100644 index 0000000000..c1efd7cd6e --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; +using OpenSim.Region.ClientStack.LindenUDP; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Avatar.Attachments +{ + /// + /// A module that just holds commands for inspecting avatar appearance. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")] + public class TempAttachmentsModule : INonSharedRegionModule + { + public void Initialise(IConfigSource configSource) + { + } + + public void AddRegion(Scene scene) + { + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + } + + public void Close() + { + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "TempAttachmentsModule"; } + } + } +} From 9bd2c1b88add5d6cc529a6882a7067200cb78ecb Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Aug 2012 01:12:27 +0100 Subject: [PATCH 4/5] As per lindn spec, disable detach and drop for temp attachments --- .../CoreModules/Avatar/Attachments/AttachmentsModule.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 77dd0f0c2f..f107be17fa 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -410,6 +410,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments UUID inventoryID = so.FromItemID; + // As per Linden spec, drop is disabled for temp attachs + if (inventoryID == UUID.Zero) + return; + // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", // so.Name, so.LocalId, inventoryID); @@ -454,6 +458,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) { + // As per Linden spec, detach (take) is disabled for temp attachs + if (so.FromItemID == UUID.Zero) + return; + lock (sp.AttachmentsSyncLock) { // Save avatar attachment information From 4bbdcfb5ee81f459df9ff9a2ac477f6419cfc279 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Aug 2012 01:45:02 +0100 Subject: [PATCH 5/5] Implement the temp attachments. UNTESTED --- .../Attachments/TempAttachmentsModule.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index c1efd7cd6e..e659ec0580 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -49,12 +49,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")] public class TempAttachmentsModule : INonSharedRegionModule { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + public void Initialise(IConfigSource configSource) { } public void AddRegion(Scene scene) { + m_scene = scene; + + IScriptModuleComms comms = scene.RequestModuleInterface(); + if (comms != null) + { + comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp"); + m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions"); + } + else + { + m_log.ErrorFormat("[TEMP ATTACHS]: Failed to register script functions"); + } } public void RemoveRegion(Scene scene) @@ -78,5 +94,33 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments { get { return "TempAttachmentsModule"; } } + + private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) + { + SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); + + if (hostPart == null) + return; + + if (hostPart.ParentGroup.IsAttachment) + return; + + IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); + if (attachmentsModule == null) + return; + + TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); + if (item == null) + return; + + if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH + return; + + ScenePresence target; + if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) + return; + + attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true); + } } }