diff --git a/OpenSim/Framework/ISceneObject.cs b/OpenSim/Framework/ISceneObject.cs
index 51479014cd..18631f17b1 100644
--- a/OpenSim/Framework/ISceneObject.cs
+++ b/OpenSim/Framework/ISceneObject.cs
@@ -39,5 +39,6 @@ namespace OpenSim.Framework
void ExtraFromXmlString(string xmlstr);
string GetStateSnapshot();
void SetState(string xmlstr, IScene s);
+ bool HasGroupChanged { get; set; }
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 929db21f71..fc92fc3df3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -276,6 +276,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (objatt != null)
{
+ // Loading the inventory from XML will have set this, but
+ // there is no way the object could have changed yet,
+ // since scripts aren't running yet. So, clear it here.
+ objatt.HasGroupChanged = false;
bool tainted = false;
if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint())
tainted = true;
@@ -486,9 +490,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
// CM / XMREngine!!!! Needed to conclude attach event
- SceneObjectSerializer.ToOriginalXmlFormat(group);
+ //SceneObjectSerializer.ToOriginalXmlFormat(group);
group.DetachToInventoryPrep();
m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
+
+ // If an item contains scripts, it's always changed.
+ // This ensures script state is saved on detach
+ foreach (SceneObjectPart p in group.Parts)
+ if (p.Inventory.ContainsScripts())
+ group.HasGroupChanged = true;
+
UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID);
m_scene.DeleteSceneObject(group, false);
return;
@@ -497,25 +508,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
}
- public void UpdateAttachmentPosition(IClientAPI client, SceneObjectGroup sog, Vector3 pos)
- {
- // If this is an attachment, then we need to save the modified
- // object back into the avatar's inventory. First we save the
- // attachment point information, then we update the relative
- // positioning (which caused this method to get driven in the
- // first place. Then we have to mark the object as NOT an
- // attachment. This is necessary in order to correctly save
- // and retrieve GroupPosition information for the attachment.
- // Then we save the asset back into the appropriate inventory
- // entry. Finally, we restore the object's attachment status.
- byte attachmentPoint = sog.GetAttachmentPoint();
- sog.UpdateGroupPosition(pos);
- sog.RootPart.IsAttachment = false;
- sog.AbsolutePosition = sog.RootPart.AttachedPos;
- UpdateKnownItem(client, sog, sog.GetFromItemID(), sog.OwnerID);
- sog.SetAttachmentPoint(attachmentPoint);
- }
-
///
/// Update the attachment asset for the new sog details if they have changed.
///
@@ -531,12 +523,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
if (grp != null)
{
- // If an item contains scripts, it's always changed.
- // This ensures script state is saved on detach
- foreach (SceneObjectPart p in grp.Parts)
- if (p.Inventory.ContainsScripts())
- grp.HasGroupChanged = true;
-
if (!grp.HasGroupChanged)
{
m_log.WarnFormat("[ATTACHMENTS MODULE]: Save request for {0} which is unchanged", grp.UUID);
@@ -548,7 +534,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
grp.UUID, grp.GetAttachmentPoint());
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
-
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
item = m_scene.InventoryService.GetItem(item);
@@ -642,7 +627,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// In case it is later dropped again, don't let
// it get cleaned up
so.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
- so.HasGroupChanged = false;
}
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 0700aa55f5..2e3db48558 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -719,15 +719,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
{
group.RootPart.Flags |= PrimFlags.Phantom;
group.RootPart.IsAttachment = true;
- }
- // If we're rezzing an attachment then don't ask
- // AddNewSceneObject() to update the client since
- // we'll be doing that later on. Scheduling more than
- // one full update during the attachment
- // process causes some clients to fail to display the
- // attachment properly.
- m_Scene.AddNewSceneObject(group, true, false);
+ // If we're rezzing an attachment then don't ask
+ // AddNewSceneObject() to update the client since
+ // we'll be doing that later on. Scheduling more
+ // than one full update during the attachment
+ // process causes some clients to fail to display
+ // the attachment properly.
+ // Also, don't persist attachments.
+ m_Scene.AddNewSceneObject(group, false, false);
+ }
+ else
+ {
+ m_Scene.AddNewSceneObject(group, true, false);
+ }
// if attachment we set it's asset id so object updates
// can reflect that, if not, we set it's position in world.
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 1d9aeb96f1..788f42b494 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -127,13 +127,20 @@ namespace OpenSim.Region.Framework.Interfaces
void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
///
- /// Update the position of an attachment
+ /// Update the user inventory with a changed attachment
///
- ///
- ///
- ///
- void UpdateAttachmentPosition(IClientAPI client, SceneObjectGroup sog, Vector3 pos);
-
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID);
}
}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 59ce090a31..ed40da9609 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -185,6 +185,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// false if the item did not exist, true if the update occurred successfully
bool UpdateInventoryItem(TaskInventoryItem item);
bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents);
+ bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged);
///
/// Remove an item from this entity's inventory
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index dd06be2df2..c4639c3716 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3255,7 +3255,6 @@ namespace OpenSim.Region.Framework.Scenes
List regions = new List(avatar.KnownChildRegionHandles);
regions.Remove(RegionInfo.RegionHandle);
m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
-
}
m_log.Debug("[Scene] Beginning ClientClosed");
m_eventManager.TriggerClientClosed(agentID, this);
@@ -3271,6 +3270,9 @@ namespace OpenSim.Region.Framework.Scenes
m_eventManager.TriggerOnRemovePresence(agentID);
m_log.Debug("[Scene] Finished OnRemovePresence");
+ if (avatar != null && (!avatar.IsChildAgent))
+ avatar.SaveChangedAttachments();
+
ForEachClient(
delegate(IClientAPI client)
{
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index a4621331d8..b2d9358c8e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -281,7 +281,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- if (!alreadyPersisted)
+ if (attachToBackup && (!alreadyPersisted))
{
sceneObject.ForceInventoryPersistence();
sceneObject.HasGroupChanged = true;
@@ -304,8 +304,10 @@ namespace OpenSim.Region.Framework.Scenes
///
protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
{
- // Ensure that we persist this new scene object
- sceneObject.HasGroupChanged = true;
+ // Ensure that we persist this new scene object if it's not an
+ // attachment
+ if (attachToBackup)
+ sceneObject.HasGroupChanged = true;
return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
}
@@ -1342,8 +1344,13 @@ namespace OpenSim.Region.Framework.Scenes
{
if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
{
- if (m_parentScene.AttachmentsModule != null)
- m_parentScene.AttachmentsModule.UpdateAttachmentPosition(remoteClient, group, pos);
+ // Set the new attachment point data in the object
+ byte attachmentPoint = group.GetAttachmentPoint();
+ group.UpdateGroupPosition(pos);
+ group.RootPart.IsAttachment = false;
+ group.AbsolutePosition = group.RootPart.AttachedPos;
+ group.SetAttachmentPoint(attachmentPoint);
+ group.HasGroupChanged = true;
}
else
{
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 79f71624aa..ee08072c29 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -586,13 +586,15 @@ namespace OpenSim.Region.Framework.Scenes
XmlNodeList nodes = doc.GetElementsByTagName("SavedScriptState");
if (nodes.Count > 0)
{
- m_savedScriptState = new Dictionary();
+ if (m_savedScriptState == null)
+ m_savedScriptState = new Dictionary();
foreach (XmlNode node in nodes)
{
if (node.Attributes["UUID"] != null)
{
UUID itemid = new UUID(node.Attributes["UUID"].Value);
- m_savedScriptState.Add(itemid, node.InnerXml);
+ if (itemid != UUID.Zero)
+ m_savedScriptState[itemid] = node.InnerXml;
}
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index be3e87f552..b615d42cc3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -4822,7 +4822,7 @@ namespace OpenSim.Region.Framework.Scenes
{
TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
item.OwnerChanged = false;
- Inventory.UpdateInventoryItem(item);
+ Inventory.UpdateInventoryItem(item, false, false);
}
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 522f75e0c8..8fcfcc5e75 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -131,12 +131,6 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
- HasInventoryChanged = true;
- if (m_part.ParentGroup != null)
- {
- m_part.ParentGroup.HasGroupChanged = true;
- }
-
IList items = new List(Items.Values);
Items.Clear();
@@ -158,12 +152,6 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
- HasInventoryChanged = true;
- if (m_part.ParentGroup != null)
- {
- m_part.ParentGroup.HasGroupChanged = true;
- }
-
IList items = new List(Items.Values);
Items.Clear();
@@ -216,8 +204,15 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
- HasInventoryChanged = true;
- m_part.ParentGroup.HasGroupChanged = true;
+ // Don't let this set the HasGroupChanged flag for attachments
+ // as this happens during rez and we don't want a new asset
+ // for each attachment each time
+ if (!m_part.ParentGroup.RootPart.IsAttachment)
+ {
+ HasInventoryChanged = true;
+ m_part.ParentGroup.HasGroupChanged = true;
+ }
+
IList items = new List(Items.Values);
foreach (TaskInventoryItem item in items)
{
@@ -824,10 +819,15 @@ namespace OpenSim.Region.Framework.Scenes
/// false if the item did not exist, true if the update occurred successfully
public bool UpdateInventoryItem(TaskInventoryItem item)
{
- return UpdateInventoryItem(item, true);
+ return UpdateInventoryItem(item, true, true);
}
public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
+ {
+ return UpdateInventoryItem(item, fireScriptEvents, true);
+ }
+
+ public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
{
m_items.LockItemsForWrite(true);
@@ -849,8 +849,11 @@ namespace OpenSim.Region.Framework.Scenes
m_inventorySerial++;
if (fireScriptEvents)
m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
- HasInventoryChanged = true;
- m_part.ParentGroup.HasGroupChanged = true;
+ if (considerChanged)
+ {
+ HasInventoryChanged = true;
+ m_part.ParentGroup.HasGroupChanged = true;
+ }
m_items.LockItemsForWrite(false);
return true;
}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cc9c445c52..dfaf06d6df 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4340,6 +4340,24 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
return(new Vector3(x,y,z));
}
+ public void SaveChangedAttachments()
+ {
+ // Need to copy this list because DetachToInventoryPrep mods it
+ List attachments = new List(Attachments.ToArray());
+ IAttachmentsModule attachmentsModule = m_scene.AttachmentsModule;
+ if (attachmentsModule != null)
+ {
+ foreach (SceneObjectGroup grp in attachments)
+ {
+ if (grp.HasGroupChanged) // Resizer scripts?
+ {
+ grp.DetachToInventoryPrep();
+ attachmentsModule.UpdateKnownItem(ControllingClient,
+ grp, grp.GetFromItemID(), grp.OwnerID);
+ }
+ }
+ }
+ }
}
}
diff --git a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs
index 33e5aa6b05..04ff83f9f3 100644
--- a/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/ObjectHandlers.cs
@@ -162,6 +162,11 @@ namespace OpenSim.Server.Handlers.Simulation
return;
}
+ if (args.ContainsKey("modified"))
+ sog.HasGroupChanged = args["modified"].AsBoolean();
+ else
+ sog.HasGroupChanged = false;
+
if ((args["state"] != null) && s.AllowScriptCrossings)
{
stateXmlStr = args["state"].AsString();
@@ -243,4 +248,4 @@ namespace OpenSim.Server.Handlers.Simulation
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index 0626ebea05..1730b95225 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -565,6 +565,7 @@ namespace OpenSim.Services.Connectors.Simulation
OSDMap args = new OSDMap(2);
args["sog"] = OSD.FromString(sog.ToXml2());
args["extra"] = OSD.FromString(sog.ExtraToXmlString());
+ args["modified"] = OSD.FromBoolean(sog.HasGroupChanged);
string state = sog.GetStateSnapshot();
if (state.Length > 0)
args["state"] = OSD.FromString(state);