From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../Avatar/Attachments/AttachmentsModule.cs | 367 +++++++++++++++------ .../Attachments/Tests/AttachmentsModuleTests.cs | 92 +++--- 2 files changed, 309 insertions(+), 150 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2f67c4e..9f52a14 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -41,6 +41,8 @@ using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Services.Interfaces; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.CoreModules.Avatar.Attachments { @@ -60,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// A value of 0 will apply no pause. The pause is specified in milliseconds. /// public int ThrottlePer100PrimsRezzed { get; set; } - + private Scene m_scene; private IInventoryAccessModule m_invAccessModule; @@ -68,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// Are attachments enabled? /// public bool Enabled { get; private set; } - + public string Name { get { return "Attachments Module"; } } public Type ReplaceableInterface { get { return null; } } @@ -86,14 +88,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments Enabled = true; } } - + public void AddRegion(Scene scene) { m_scene = scene; if (Enabled) { // Only register module with scene if it is enabled. All callers check for a null attachments module. - // Ideally, there should be a null attachments module for when this core attachments module has been + // Ideally, there should be a null attachments module for when this core attachments module has been // disabled. Registering only when enabled allows for other attachments module implementations. m_scene.RegisterModuleInterface(this); m_scene.EventManager.OnNewClient += SubscribeToClientEvents; @@ -180,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private void HandleScriptStateChange(uint localID, bool started) { SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); - if (sog != null && sog.IsAttachment) + if (sog != null && sog.IsAttachment) { if (!started) { @@ -197,21 +199,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } } - - public void RemoveRegion(Scene scene) + + public void RemoveRegion(Scene scene) { m_scene.UnregisterModuleInterface(this); if (Enabled) m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; } - + public void RegionLoaded(Scene scene) { m_invAccessModule = m_scene.RequestModuleInterface(); } - - public void Close() + + public void Close() { RemoveRegion(m_scene); } @@ -269,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); // m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", +// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", // ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); so.SetState(ad.AttachmentObjectStates[i++], m_scene); @@ -294,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { if (DebugLevel > 0) m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", + "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", m_scene.Name, sp.Name); return; @@ -303,6 +305,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (DebugLevel > 0) m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); + XmlDocument doc = new XmlDocument(); + doc.XmlResolver=null; + string stateData = String.Empty; + + IAttachmentsService attServ = m_scene.RequestModuleInterface(); + if (attServ != null) + { + m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); + stateData = attServ.Get(sp.UUID.ToString()); + if (stateData != String.Empty) + { + try + { + doc.LoadXml(stateData); + } + catch { } + } + } + + Dictionary itemData = new Dictionary(); + + XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); + if (nodes.Count > 0) + { + foreach (XmlNode n in nodes) + { + XmlElement elem = (XmlElement)n; + string itemID = elem.GetAttribute("ItemID"); + string xml = elem.InnerXml; + + itemData[new UUID(itemID)] = xml; + } + } + + List attachments = sp.Appearance.GetAttachments(); // Let's get all items at once, so they get cached @@ -322,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down // But they're not used anyway, the item is being looked up for now, so let's proceed. - //if (UUID.Zero == assetID) + //if (UUID.Zero == assetID) //{ // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); // continue; @@ -330,10 +367,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments try { + string xmlData; + XmlDocument d = null; + UUID asset; + if (itemData.TryGetValue(attach.ItemID, out xmlData)) + { + d = new XmlDocument(); + d.XmlResolver=null; + d.LoadXml(xmlData); + m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID); + } + // If we're an NPC then skip all the item checks and manipulations since we don't have an // inventory right now. RezSingleAttachmentFromInventoryInternal( - sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); + sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d); } catch (Exception e) { @@ -361,26 +409,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments Dictionary scriptStates = new Dictionary(); - foreach (SceneObjectGroup so in attachments) + + if (sp.PresenceType != PresenceType.Npc) { - // Scripts MUST be snapshotted before the object is - // removed from the scene because doing otherwise will - // clobber the run flag - // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from - // scripts performing attachment operations at the same time. Getting object states stops the scripts. - scriptStates[so] = PrepareScriptInstanceForSave(so, false); + foreach (SceneObjectGroup so in attachments) + { + // Scripts MUST be snapshotted before the object is + // removed from the scene because doing otherwise will + // clobber the run flag + // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from + // scripts performing attachment operations at the same time. Getting object states stops the scripts. + scriptStates[so] = PrepareScriptInstanceForSave(so, false); + } -// m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}", -// so.Name, sp.Name, m_scene.Name, scriptStates[so]); + lock (sp.AttachmentsSyncLock) + { + foreach (SceneObjectGroup so in attachments) + UpdateDetachedObject(sp, so, scriptStates[so]); + sp.ClearAttachments(); + } } - - lock (sp.AttachmentsSyncLock) + else { - foreach (SceneObjectGroup so in attachments) - UpdateDetachedObject(sp, so, scriptStates[so]); - - sp.ClearAttachments(); + lock (sp.AttachmentsSyncLock) + { + foreach (SceneObjectGroup so in attachments) + UpdateDetachedObject(sp, so, String.Empty); + sp.ClearAttachments(); + } } } @@ -392,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (DebugLevel > 0) m_log.DebugFormat( "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", - m_scene.RegionInfo.RegionName, sp.Name, silent); + m_scene.RegionInfo.RegionName, sp.Name, silent); foreach (SceneObjectGroup sop in sp.GetAttachments()) { @@ -401,21 +457,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments sp.ClearAttachments(); } - - public bool AttachObject( - IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append) + + public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, + bool addToInventory, bool append) { if (!Enabled) return false; - group.DetachFromBackup(); - - bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); - - if (!success) - group.AttachToBackup(); - - return success; + return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append); } /// @@ -428,10 +477,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// If true then add object to user inventory. /// If true then scripts are resumed on the attached object. - /// Append to attachment point rather than replace. - private bool AttachObjectInternal( - IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append) + private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, + bool silent, bool addToInventory, bool resumeScripts, bool append) { +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", +// group.Name, group.LocalId, sp.Name, attachmentPt, silent); + + if (group.GetSittingAvatarsCount() != 0) { if (DebugLevel > 0) @@ -442,7 +495,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return false; } + List attachments = sp.GetAttachments(attachmentPt); + if (attachments.Contains(group)) + { +// if (DebugLevel > 0) +// m_log.WarnFormat( +// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", +// group.Name, group.LocalId, sp.Name, attachmentPt); + + return false; + } + Vector3 attachPos = group.AbsolutePosition; + + // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should + // be removed when that functionality is implemented in opensim + attachmentPt &= 0x7f; + // 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. @@ -470,7 +539,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; attachPos = group.RootPart.AttachedPos; - group.HasGroupChanged = true; } // if we still didn't find a suitable attachment point....... @@ -481,21 +549,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments attachPos = Vector3.Zero; } - group.AttachmentPoint = attachmentPt; - group.AbsolutePosition = attachPos; - - List attachments = sp.GetAttachments(attachmentPt); - - if (attachments.Contains(group)) - { - if (DebugLevel > 0) - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", - group.Name, group.LocalId, sp.Name, attachmentPt); - - return false; - } - // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones while (attachments.Count >= 5) { @@ -514,11 +567,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } + group.DetachFromBackup(); + lock (sp.AttachmentsSyncLock) { + group.AttachmentPoint = attachmentPt; + group.RootPart.AttachedPos = attachPos; + if (addToInventory && sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); - + AttachToAgent(sp, group, attachmentPt, attachPos, silent); if (resumeScripts) @@ -529,8 +587,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.ResumeScripts(); } + else // Do this last so that event listeners have access to all the effects of the attachment - m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); + // this can't be done when creating scripts: + // scripts do internal enqueue of attach event + // and not all scripts are loaded at this point + m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); } return true; @@ -546,7 +608,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); } - public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) + public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) + { + return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null); + } + + public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc) { if (!Enabled) return null; @@ -557,8 +624,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); // We check the attachments in the avatar appearance here rather than the objects attached to the - // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are - // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done + // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are + // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done // because pre-outfit folder viewers (most version 1 viewers) require it. bool alreadyOn = false; List existingAttachments = sp.Appearance.GetAttachments(); @@ -584,7 +651,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments bool append = (AttachmentPt & 0x80) != 0; AttachmentPt &= 0x7f; - return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); + return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc); } public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List> rezlist) @@ -594,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (DebugLevel > 0) m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", + "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", rezlist.Count, sp.Name, m_scene.Name); foreach (KeyValuePair rez in rezlist) @@ -605,7 +672,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) { - DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); + Vector3 pos = new Vector3(2.5f, 0f, 0f); + pos *= ((ScenePresence)sp).Rotation; + pos += sp.AbsolutePosition; + DetachSingleAttachmentToGround(sp, soLocalId, pos, Quaternion.Identity); } public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) @@ -649,26 +719,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (changed && m_scene.AvatarFactory != null) m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); + so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint; + sp.RemoveAttachment(so); so.FromItemID = UUID.Zero; + so.AttachedAvatar = UUID.Zero; + so.ClearPartAttachmentData(); + SceneObjectPart rootPart = so.RootPart; + + rootPart.SetParentLocalId(0); so.AbsolutePosition = absolutePos; if (absoluteRot != Quaternion.Identity) { so.UpdateGroupRotationR(absoluteRot); } - so.AttachedAvatar = UUID.Zero; - rootPart.SetParentLocalId(0); - so.ClearPartAttachmentData(); - rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); - so.HasGroupChanged = true; - so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint; - rootPart.Rezzed = DateTime.Now; + rootPart.RemFlag(PrimFlags.TemporaryOnRez); + + so.ApplyPhysics(); + + rootPart.Rezzed = DateTime.Now; so.AttachToBackup(); m_scene.EventManager.TriggerParcelPrimCountTainted(); - rootPart.ScheduleFullUpdate(); + rootPart.ClearUndoState(); List uuids = new List(); @@ -678,6 +753,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); + + // Attach (NULL) stops scripts. We don't want that. Resume them. + so.ResumeScripts(); + so.HasGroupChanged = true; + so.RootPart.ScheduleFullUpdate(); + so.ScheduleGroupForTerseUpdate(); } public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) @@ -691,9 +772,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; } + // If this didn't come from inventory, it also shouldn't go there + // on detach. It's likely a temp attachment. + if (so.FromItemID == UUID.Zero) + { + // Retirn value is ignored + PrepareScriptInstanceForSave(so, true); + + lock (sp.AttachmentsSyncLock) + { + bool changed = sp.Appearance.DetachAttachment(so.FromItemID); + if (changed && m_scene.AvatarFactory != null) + m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); + + sp.RemoveAttachment(so); + } + + m_scene.DeleteSceneObject(so, false, false); + so.RemoveScriptInstances(true); + so.Clear(); + + return; + } + if (DebugLevel > 0) m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", + "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); // Scripts MUST be snapshotted before the object is @@ -716,14 +820,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments UpdateDetachedObject(sp, so, scriptedState); } } - + public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) { if (!Enabled) return; sog.UpdateGroupPosition(pos); - sog.HasGroupChanged = true; + sog.HasGroupChanged = true; } #endregion @@ -732,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This is public but is not part of the IAttachmentsModule interface. // RegionCombiner module needs to poke at it to deliver client events. - // This breaks the encapsulation of the module and should get fixed somehow. + // This breaks the encapsulation of the module and should get fixed somehow. public void SubscribeToClientEvents(IClientAPI client) { client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv; @@ -745,7 +849,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This is public but is not part of the IAttachmentsModule interface. // RegionCombiner module needs to poke at it to deliver client events. - // This breaks the encapsulation of the module and should get fixed somehow. + // This breaks the encapsulation of the module and should get fixed somehow. public void UnsubscribeFromClientEvents(IClientAPI client) { client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv; @@ -791,11 +895,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); - InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); - item = m_scene.InventoryService.GetItem(item); + InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, grp.FromItemID); if (item != null) { + // attach is rez, need to update permissions + item.Flags &= ~(uint)(InventoryItemFlags.ObjectSlamPerm | InventoryItemFlags.ObjectOverwriteBase | + InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | + InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner); + + uint permsBase = (uint)(PermissionMask.Copy | PermissionMask.Transfer | + PermissionMask.Modify | PermissionMask.Move | + PermissionMask.Export | PermissionMask.FoldedMask); + + permsBase &= grp.CurrentAndFoldedNextPermissions(); + permsBase |= (uint)PermissionMask.Move; + item.BasePermissions = permsBase; + item.CurrentPermissions = permsBase; + item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask | (uint)PermissionMask.Move; + item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask; + item.GroupPermissions = permsBase & grp.RootPart.GroupMask; + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + (uint)PermissionMask.Export | + (uint)PermissionMask.FoldedMask); // Preserve folded permissions ?? + AssetBase asset = m_scene.CreateAsset( grp.GetPartName(grp.LocalId), grp.GetPartDescription(grp.LocalId), @@ -826,7 +953,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// Attach this scene object to the given avatar. /// /// - /// This isn't publicly available since attachments should always perform the corresponding inventory + /// This isn't publicly available since attachments should always perform the corresponding inventory /// operation (to show the attach in user inventory and update the asset with positional information). /// /// @@ -846,16 +973,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); - so.AttachedAvatar = sp.UUID; - if (so.RootPart.PhysActor != null) - so.RootPart.RemoveFromPhysics(); + foreach (SceneObjectPart part in so.Parts) + { +// if (part.KeyframeMotion != null) +// part.KeyframeMotion.Suspend(); + + if (part.PhysActor != null) + { + part.RemoveFromPhysics(); + } + } - so.AbsolutePosition = attachOffset; - so.RootPart.AttachedPos = attachOffset; - so.IsAttachment = true; so.RootPart.SetParentLocalId(sp.LocalId); + so.AttachedAvatar = sp.UUID; so.AttachmentPoint = attachmentpoint; + so.RootPart.AttachedPos = attachOffset; + so.AbsolutePosition = attachOffset; + so.IsAttachment = true; sp.AddAttachment(so); @@ -879,7 +1014,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update // will succeed, as that will not update if an attachment is selected. - so.IsSelected = false; // fudge.... + so.IsSelected = false; // fudge.... so.ScheduleGroupForFullUpdate(); } @@ -923,7 +1058,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// This involves triggering the detach event and getting the script state (which also stops the script) - /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a + /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a /// running script is performing attachment operations. /// /// @@ -939,7 +1074,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (fireDetachEvent) { m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); - // Allow detach event time to do some work before stopping the script Thread.Sleep(2); } @@ -971,6 +1105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Remove the object from the scene so no more updates // are sent. Doing this before the below changes will ensure // updates can't cause "HUD artefacts" + m_scene.DeleteSceneObject(so, false, false); // Prepare sog for storage @@ -989,23 +1124,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Now, remove the scripts so.RemoveScriptInstances(true); + so.Clear(); } protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( - IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) + IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc) { if (m_invAccessModule == null) return null; SceneObjectGroup objatt; + UUID rezGroupID; + + // This will fail if the user aborts login. sp will exist + // but ControllintClient will be null. + try + { + rezGroupID = sp.ControllingClient.ActiveGroupId; + } + catch + { + return null; + } + if (itemID != UUID.Zero) objatt = m_invAccessModule.RezObject(sp.ControllingClient, - itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + itemID, rezGroupID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, sp.UUID, true); else objatt = m_invAccessModule.RezObject(sp.ControllingClient, - null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + null, rezGroupID, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, sp.UUID, true); if (objatt == null) @@ -1018,7 +1167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } else if (itemID == UUID.Zero) { - // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is + // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory // we will satisfy this requirement by inserting a random UUID. objatt.FromItemID = UUID.Random(); @@ -1043,6 +1192,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This will throw if the attachment fails try { + if (doc != null) + { + objatt.LoadScriptState(doc); + objatt.ResetOwnerChangeFlag(); + } + AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); } catch (Exception e) @@ -1058,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } if (tainted) - objatt.HasGroupChanged = true; + objatt.HasGroupChanged = true; if (ThrottlePer100PrimsRezzed > 0) { @@ -1100,8 +1255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; } - InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); - item = m_scene.InventoryService.GetItem(item); + InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, itemID); if (item == null) return; @@ -1185,7 +1339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (part == null) return; - if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) + SceneObjectGroup group = part.ParentGroup; + + if (!m_scene.Permissions.CanTakeObject(group, sp)) { remoteClient.SendAgentAlertMessage( "You don't have sufficient permissions to attach this object", false); @@ -1197,7 +1353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments AttachmentPt &= 0x7f; // Calls attach with a Zero position - if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) + if (AttachObject(sp, group , AttachmentPt, false, true, append)) { if (DebugLevel > 0) m_log.Debug( @@ -1205,7 +1361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments + ", AttachmentPoint: " + AttachmentPt); // Save avatar attachment information - m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); + m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); } } catch (Exception e) @@ -1222,7 +1378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); - if (sp != null && group != null && group.FromItemID != UUID.Zero) + if (sp != null && group != null) DetachSingleAttachmentToInv(sp, group); } @@ -1256,7 +1412,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (sp != null) DetachSingleAttachmentToGround(sp, soLocalId); } - #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 0ac3add..941853c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -55,6 +55,7 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { +/* /// /// Attachment tests /// @@ -200,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(so.Backup, Is.True); m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); + scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); // Check status on scene presence Assert.That(sp.HasAttachments(), Is.True); @@ -215,11 +216,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.Backup, Is.False); // Check item status - Assert.That( - sp.Appearance.GetAttachpoint(attSo.FromItemID), - Is.EqualTo((int)AttachmentPoint.Chest)); +// Assert.That( +// sp.Appearance.GetAttachpoint(attSo.FromItemID), +// Is.EqualTo((int)AttachmentPoint.Chest)); - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); + InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); Assert.That(attachmentItem, Is.Not.Null); Assert.That(attachmentItem.Name, Is.EqualTo(attName)); @@ -262,11 +263,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsTemporary, Is.False); // Check item status - Assert.That( - sp.Appearance.GetAttachpoint(attSo.FromItemID), - Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That( +// sp.Appearance.GetAttachpoint(attSo.FromItemID), +// Is.EqualTo((int)AttachmentPoint.LeftHand)); - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); + InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); Assert.That(attachmentItem, Is.Not.Null); Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); @@ -281,7 +282,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Test wearing a different attachment from the ground. { - scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); + scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); // Check status on scene presence Assert.That(sp.HasAttachments(), Is.True); @@ -295,11 +296,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsTemporary, Is.False); // Check item status - Assert.That( - sp.Appearance.GetAttachpoint(attSo.FromItemID), - Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That( +// sp.Appearance.GetAttachpoint(attSo.FromItemID), +// Is.EqualTo((int)AttachmentPoint.LeftHand)); - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); + InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); Assert.That(attachmentItem, Is.Not.Null); Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); @@ -314,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Test rewearing an already worn attachment from ground. Nothing should happen. { - scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); + scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); // Check status on scene presence Assert.That(sp.HasAttachments(), Is.True); @@ -328,11 +329,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsTemporary, Is.False); // Check item status - Assert.That( - sp.Appearance.GetAttachpoint(attSo.FromItemID), - Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That( +// sp.Appearance.GetAttachpoint(attSo.FromItemID), +// Is.EqualTo((int)AttachmentPoint.LeftHand)); - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); + InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); Assert.That(attachmentItem, Is.Not.Null); Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); @@ -372,7 +373,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, true, false); + scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); Assert.That(sp.HasAttachments(), Is.False); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); @@ -410,8 +411,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.IsFalse(attSo.Backup); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events @@ -435,8 +436,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsTemporary, Is.False); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events @@ -474,8 +475,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsAttachment); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events @@ -484,7 +485,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Test wearing a second attachment at the same position // Until multiple attachments at one point is implemented, this will remove the first attachment - // This test relies on both attachments having the same default attachment point (in this case LeftHand + // This test relies on both attachments having the same default attachment point (in this case LeftHand // since none other has been set). { scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); @@ -499,8 +500,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsAttachment); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events @@ -521,8 +522,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsAttachment); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events @@ -556,6 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // In the future, we need to be able to do this programatically more predicably. scene.EventManager.OnChatFromWorld += OnChatFromWorld; + m_chatEvent.Reset(); scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); m_chatEvent.WaitOne(60000); @@ -596,10 +598,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attachments.Count, Is.EqualTo(0)); // Check appearance status - Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0)); +// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0)); // Check item status - Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null); + Assert.That(scene.InventoryService.GetItem(sp.UUID, attItem.ID), Is.Null); // Check object in scene SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att"); @@ -634,7 +636,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attachments.Count, Is.EqualTo(0)); // Check item status - Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); +// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); @@ -669,15 +671,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // In the future, we need to be able to do this programatically more predicably. scene.EventManager.OnChatFromWorld += OnChatFromWorld; + m_chatEvent.Reset(); SceneObjectGroup rezzedSo - = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); // Wait for chat to signal rezzed script has been started. m_chatEvent.WaitOne(60000); scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); - InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); + InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem.Owner, userItem.ID); AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); // TODO: It would probably be better here to check script state via the saving and retrieval of state @@ -689,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); // Re-rez the attachment to check script running state - SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); // Wait for chat to signal rezzed script has been started. m_chatEvent.WaitOne(60000); @@ -719,13 +722,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); - SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; + UUID rezzedAttID = presence.GetAttachments()[0].UUID; m_numberOfAttachEventsFired = 0; scene.CloseAgent(presence.UUID, false); // Check that we can't retrieve this attachment from the scene. - Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); + Assert.That(scene.GetSceneObjectGroup(rezzedAttID), Is.Null); // Check events Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); @@ -802,7 +805,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } -/* + [Test] public void TestSameSimulatorNeighbouringRegionsTeleportV1() { @@ -842,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour - lscm.ServiceVersion = 0.1f; + //lscm.ServiceVersion = 0.1f; UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); @@ -910,7 +913,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check events Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } -*/ + [Test] public void TestSameSimulatorNeighbouringRegionsTeleportV2() @@ -972,8 +975,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Both these operations will occur on different threads and will wait for each other. // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 // test protocol, where we are trying to avoid unpredictable async operations in regression tests. - tc.OnTestClientSendRegionTeleport - += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) + tc.OnTestClientSendRegionTeleport + += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); m_numberOfAttachEventsFired = 0; @@ -1023,4 +1026,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } } +*/ } -- cgit v1.1