diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index e0df2881ed..0fc467bc43 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -411,6 +411,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// Rez an object into the scene from the user's inventory /// + /// 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. /// /// /// @@ -500,13 +502,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess group.RootPart.IsAttachment = true; } - m_Scene.AddNewSceneObject(group, 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, @@ -562,6 +568,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess part.GroupMask = 0; // DO NOT propagate here } } + group.ApplyNextOwnerPermissions(); } } @@ -569,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart part in partList) { if (part.OwnerID != item.Owner) - { + { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); @@ -591,10 +598,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { group.ClearPartAttachmentData(); } - } - - if (!attachment) - { + // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6df25d6e29..5f3cd8cf4d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1842,9 +1842,18 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnAttach(localID, itemID, avatarID); } - public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, - uint AttachmentPt) + /// + /// Called when the client receives a request to rez a single attachment on to the avatar from inventory + /// (RezSingleAttachmentFromInv packet). + /// + /// + /// + /// + /// + public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { + m_log.DebugFormat("[USER INVENTORY]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); + SceneObjectGroup att = m_sceneGraph.RezSingleAttachment(remoteClient, itemID, AttachmentPt); if (att == null) @@ -1856,9 +1865,20 @@ namespace OpenSim.Region.Framework.Scenes return RezSingleAttachment(att, remoteClient, itemID, AttachmentPt); } - public UUID RezSingleAttachment(SceneObjectGroup att, - IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + /// + /// Update the user inventory to reflect an attachment + /// + /// + /// + /// + /// + /// + public UUID RezSingleAttachment(SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { + m_log.DebugFormat( + "[USER INVENTORY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", + remoteClient.Name, att.Name, itemID); + if (!att.IsDeleted) AttachmentPt = att.RootPart.AttachmentPoint; @@ -1897,8 +1917,19 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent); } + /// + /// This registers the item as attached in a user's inventory + /// + /// + /// + /// + /// public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) { +// m_log.DebugFormat( +// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", +// att.Name, remoteClient.Name, AttachmentPt, itemID); + if (UUID.Zero == itemID) { m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); @@ -1926,10 +1957,7 @@ namespace OpenSim.Region.Framework.Scenes presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); if (m_AvatarFactory != null) - { m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } } @@ -2012,6 +2040,7 @@ namespace OpenSim.Region.Framework.Scenes { sog.SetOwnerId(ownerID); sog.SetGroup(groupID, remoteClient); + sog.ScheduleGroupForFullUpdate(); foreach (SceneObjectPart child in sog.Children.Values) child.Inventory.ChangeInventoryOwner(ownerID); @@ -2033,6 +2062,7 @@ namespace OpenSim.Region.Framework.Scenes sog.SetOwnerId(groupID); sog.ApplyNextOwnerPermissions(); } + } foreach (uint localID in localIDs) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 5e5a52e981..a880fe7d59 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1906,14 +1906,22 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat( // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); + SceneObjectGroup sceneObject = null; + // If an entity creator has been registered for this prim type then use that if (m_entityCreators.ContainsKey((PCode)shape.PCode)) - return m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + { + sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + } + else + { + // Otherwise, use this default creation code; + sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); + AddNewSceneObject(sceneObject, true); + sceneObject.SetGroup(groupID, null); + } - // Otherwise, use this default creation code; - SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); + sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; } @@ -1941,7 +1949,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Add a newly created object to the scene + /// Add a newly created object to the scene. Updates are also sent to viewers. /// /// /// @@ -1950,8 +1958,25 @@ namespace OpenSim.Region.Framework.Scenes /// public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) { - return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup); + return AddNewSceneObject(sceneObject, attachToBackup, true); } + + /// + /// Add a newly created object to the scene + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) + { + return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); + } /// /// Delete every object from the scene @@ -3143,7 +3168,6 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; m_sceneGridService.KiPrimitive += SendKillObject; m_sceneGridService.OnGetLandData += GetLandData; - } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b7fcd7d558..22613e925f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -229,7 +229,7 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup); + return AddSceneObject(sceneObject, attachToBackup, true); } /// @@ -244,12 +244,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// true if the object was added, false if an object with the same uuid was already in the scene /// - protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { // Ensure that we persist this new scene object sceneObject.HasGroupChanged = true; - return AddSceneObject(sceneObject, attachToBackup); + return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } /// @@ -261,12 +261,19 @@ namespace OpenSim.Region.Framework.Scenes /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// - /// true if the object was added, false if an object with the same uuid was already in the scene + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene /// - protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; + + bool alreadyExisted = false; if (m_parentScene.m_clampPrimSize) { @@ -287,6 +294,9 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); + if (sendClientUpdates) + sceneObject.ScheduleGroupForFullUpdate(); + lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) @@ -310,12 +320,14 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } } - - return true; + } + else + { + alreadyExisted = true; } } - return false; + return alreadyExisted; } /// @@ -525,7 +537,10 @@ namespace OpenSim.Region.Framework.Scenes itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, remoteClient.AgentId, true); - +// m_log.DebugFormat( +// "[SCENE GRAPH]: Retrieved single object {0} for attachment to {1} on point {2}", +// objatt.Name, remoteClient.Name, AttachmentPt); + if (objatt != null) { bool tainted = false; @@ -533,7 +548,7 @@ namespace OpenSim.Region.Framework.Scenes tainted = true; AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); - objatt.ScheduleGroupForFullUpdate(); + //objatt.ScheduleGroupForFullUpdate(); if (tainted) objatt.HasGroupChanged = true; @@ -544,8 +559,16 @@ namespace OpenSim.Region.Framework.Scenes // Do this last so that event listeners have access to all the effects of the attachment m_parentScene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); } + else + { + m_log.WarnFormat( + "[SCENE GRAPH]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", + itemID, remoteClient.Name, AttachmentPt); + } + return objatt; } + return null; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c5a6171207..c14b39ad85 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -567,8 +567,10 @@ namespace OpenSim.Region.Framework.Scenes } ApplyPhysics(m_scene.m_physicalPrim); - - ScheduleGroupForFullUpdate(); + + // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled + // for the same object with very different properties. The caller must schedule the update. + //ScheduleGroupForFullUpdate(); } public Vector3 GroupScale() @@ -956,10 +958,11 @@ namespace OpenSim.Region.Framework.Scenes // don't attach attachments to child agents if (avatar.IsChildAgent) return; +// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name); + DetachFromBackup(); // Remove from database and parcel prim count - // m_scene.DeleteFromStorage(UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); @@ -985,7 +988,6 @@ namespace OpenSim.Region.Framework.Scenes SetAttachmentPoint(Convert.ToByte(attachmentpoint)); avatar.AddAttachment(this); - m_log.Debug("[SOG]: Added attachment " + UUID + " to avatar " + avatar.UUID); if (!silent) { @@ -1002,6 +1004,12 @@ namespace OpenSim.Region.Framework.Scenes ScheduleGroupForFullUpdate(); } } + else + { + m_log.WarnFormat( + "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", + UUID, agentID, Scene.RegionInfo.RegionName); + } } public byte GetAttachmentPoint() @@ -1986,6 +1994,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + RootPart.AddFullUpdateToAvatar(presence); lock (m_parts) @@ -2000,6 +2010,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleTerseUpdateToAvatar(ScenePresence presence) { +// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + lock (m_parts) { foreach (SceneObjectPart part in m_parts.Values) @@ -2014,6 +2026,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); + checkAtTargets(); RootPart.ScheduleFullUpdate(); @@ -2032,6 +2046,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForTerseUpdate() { +// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); + lock (m_parts) { foreach (SceneObjectPart part in m_parts.Values) @@ -2045,9 +2061,11 @@ namespace OpenSim.Region.Framework.Scenes /// Immediately send a full update for this scene object. /// public void SendGroupFullUpdate() - { + { if (IsDeleted) return; + +// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); RootPart.SendFullUpdateToAllClients(); @@ -2064,7 +2082,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Immediately send an update for this scene object's root prim only. /// This is for updates regarding the object as a whole, and none of its parts in particular. - /// Note: this may not be cused by opensim (it probably should) but it's used by + /// Note: this may not be used by opensim (it probably should) but it's used by /// external modules. /// public void SendGroupRootTerseUpdate() @@ -2079,6 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_scene == null) // Need to check here as it's null during object creation return; + m_scene.SceneGraph.AddToUpdateList(this); } @@ -3557,7 +3576,9 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; } - ScheduleGroupForFullUpdate(); + // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled + // for the same object with very different properties. The caller must schedule the update. + //ScheduleGroupForFullUpdate(); } public void TriggerScriptChangedEvent(Changed val) diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 3c7adf5419..4e7ef51bd8 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index bf693a18ec..dc65ffd07f 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -31,14 +31,14 @@ [AvatarService] LocalServiceModule = "OpenSim.Services.AvatarService.dll:AvatarService" - ConnectionString = "URI=file:avatars.db,version=3" + ; ConnectionString = "URI=file:avatars.db,version=3" [AuthorizationService] LocalServiceModule = "OpenSim.Services.AuthorizationService.dll:AuthorizationService" [AuthenticationService] LocalServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - ConnectionString = "URI=file:auth.db,version=3" + ; ConnectionString = "URI=file:auth.db,version=3" [GridService] LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" @@ -51,7 +51,7 @@ [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ConnectionString = "URI=file:userprofiles.db,version=3" + ; ConnectionString = "URI=file:userprofiles.db,version=3" ;; These are for creating new accounts AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" @@ -60,7 +60,7 @@ [FriendsService] LocalServiceModule = "OpenSim.Services.FriendsService.dll" - ConnectionString = "URI=file:friends.db,version=3" + ; ConnectionString = "URI=file:friends.db,version=3" [Friends] Connector = "OpenSim.Services.FriendsService.dll"