* Fix mantis 345 - it is now possible to duplicate prims directly in the region again without breakage

* This includes their inventories
* Also, this revision properly synchronizes prim inventory crud.
ThreadPoolClientBranch
Justin Clarke Casey 2008-01-16 20:27:12 +00:00
parent c3061717d0
commit b33da2538e
5 changed files with 179 additions and 112 deletions

View File

@ -36,7 +36,13 @@ using System;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
public class TaskInventoryDictionary : Dictionary<LLUUID, TaskInventoryItem>, IXmlSerializable /// <summary>
/// A dictionary for task inventory.
///
/// This class is not thread safe. Callers must synchronize on Dictionary methods.
/// </summary>
public class TaskInventoryDictionary : Dictionary<LLUUID, TaskInventoryItem>,
ICloneable, IXmlSerializable
{ {
private static XmlSerializer tiiSerializer = new XmlSerializer(typeof(TaskInventoryItem)); private static XmlSerializer tiiSerializer = new XmlSerializer(typeof(TaskInventoryItem));
@ -85,20 +91,39 @@ namespace OpenSim.Framework
// see IXmlSerializable // see IXmlSerializable
public void WriteXml(XmlWriter writer) public void WriteXml(XmlWriter writer)
{
lock (this)
{ {
foreach (TaskInventoryItem item in Values) foreach (TaskInventoryItem item in Values)
{ {
tiiSerializer.Serialize(writer, item); tiiSerializer.Serialize(writer, item);
} }
}
//tiiSerializer.Serialize(writer, Values); //tiiSerializer.Serialize(writer, Values);
} }
// see ICloneable
public Object Clone()
{
TaskInventoryDictionary clone = new TaskInventoryDictionary();
lock (this)
{
foreach (LLUUID uuid in Keys)
{
clone.Add(uuid, (TaskInventoryItem)this[uuid].Clone());
}
}
return clone;
}
} }
/// <summary> /// <summary>
/// Represents an item in a task inventory /// Represents an item in a task inventory
/// </summary> /// </summary>
public class TaskInventoryItem public class TaskInventoryItem : ICloneable
{ {
/// <summary> /// <summary>
/// XXX This should really be factored out into some constants class. /// XXX This should really be factored out into some constants class.
@ -143,16 +168,6 @@ namespace OpenSim.Framework
String.Empty String.Empty
}; };
/// <summary>
/// Reset the LLUUIDs for this item.
/// </summary>
/// <param name="partID">The new part ID to which this item belongs</param>
public void ResetIDs(LLUUID partID)
{
ItemID = LLUUID.Random();
ParentPartID = partID;
}
public LLUUID ItemID = LLUUID.Zero; public LLUUID ItemID = LLUUID.Zero;
public LLUUID ParentID = LLUUID.Zero; //parent folder id public LLUUID ParentID = LLUUID.Zero; //parent folder id
@ -175,5 +190,21 @@ namespace OpenSim.Framework
public uint CreationDate = 0; public uint CreationDate = 0;
public LLUUID ParentPartID = LLUUID.Zero; public LLUUID ParentPartID = LLUUID.Zero;
/// <summary>
/// Reset the LLUUIDs for this item.
/// </summary>
/// <param name="partID">The new part ID to which this item belongs</param>
public void ResetIDs(LLUUID partID)
{
ItemID = LLUUID.Random();
ParentPartID = partID;
}
// See ICloneable
public Object Clone()
{
return MemberwiseClone();
}
} }
} }

View File

@ -928,17 +928,22 @@ namespace OpenSim.Region.Environment.Scenes
{ {
SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID); SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID);
copy.AbsolutePosition = copy.AbsolutePosition + offset; copy.AbsolutePosition = copy.AbsolutePosition + offset;
copy.ResetIDs();
lock (Entities) lock (Entities)
{ {
Entities.Add(copy.UUID, copy); Entities.Add(copy.UUID, copy);
} }
m_numPrim++; m_numPrim++;
copy.StartScripts();
copy.ScheduleGroupForFullUpdate(); copy.ScheduleGroupForFullUpdate();
} }
} }
else else
{ {
MainLog.Instance.Warn("client", "Attempted to duplicate nonexistant prim"); MainLog.Instance.Warn("SCENE", "Attempted to duplicate nonexistant prim id {0}", GroupID);
} }
} }

View File

@ -572,9 +572,8 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="part"></param> /// <param name="part"></param>
public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{ {
SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID); SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
newPart.SetParent(this); newPart.SetParent(this);
newPart.LinkNum = m_parts.Count;
m_parts.Add(newPart.UUID, newPart); m_parts.Add(newPart.UUID, newPart);
SetPartAsRoot(newPart); SetPartAsRoot(newPart);
} }
@ -602,9 +601,8 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="part"></param> /// <param name="part"></param>
public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{ {
SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID); SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
newPart.SetParent(this); newPart.SetParent(this);
newPart.LinkNum = m_parts.Count;
m_parts.Add(newPart.UUID, newPart); m_parts.Add(newPart.UUID, newPart);
SetPartAsNonRoot(newPart); SetPartAsNonRoot(newPart);
} }

View File

@ -87,6 +87,8 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
/// <param name="linkNum'>Link number for the part</param> /// <param name="linkNum'>Link number for the part</param>
public void ResetInventoryIDs() public void ResetInventoryIDs()
{
lock (TaskInventory)
{ {
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values); IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
TaskInventory.Clear(); TaskInventory.Clear();
@ -97,11 +99,14 @@ namespace OpenSim.Region.Environment.Scenes
TaskInventory.Add(item.ItemID, item); TaskInventory.Add(item.ItemID, item);
} }
} }
}
/// <summary> /// <summary>
/// Start all the scripts contained in this prim's inventory /// Start all the scripts contained in this prim's inventory
/// </summary> /// </summary>
public void StartScripts() public void StartScripts()
{
lock (m_taskInventory)
{ {
foreach (TaskInventoryItem item in m_taskInventory.Values) foreach (TaskInventoryItem item in m_taskInventory.Values)
{ {
@ -112,6 +117,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
} }
}
/// <summary> /// <summary>
/// Start a script which is in this prim's inventory. /// Start a script which is in this prim's inventory.
@ -148,6 +154,8 @@ namespace OpenSim.Region.Environment.Scenes
/// A <see cref="LLUUID"/> /// A <see cref="LLUUID"/>
/// </param> /// </param>
public void StartScript(LLUUID itemId) public void StartScript(LLUUID itemId)
{
lock (m_taskInventory)
{ {
if (m_taskInventory.ContainsKey(itemId)) if (m_taskInventory.ContainsKey(itemId))
{ {
@ -160,7 +168,7 @@ namespace OpenSim.Region.Environment.Scenes
"Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
itemId, Name, UUID); itemId, Name, UUID);
} }
}
} }
/// <summary> /// <summary>
@ -191,7 +199,12 @@ namespace OpenSim.Region.Environment.Scenes
item.ParentID = m_folderID; item.ParentID = m_folderID;
item.CreationDate = 1000; item.CreationDate = 1000;
item.ParentPartID = UUID; item.ParentPartID = UUID;
lock (m_taskInventory)
{
m_taskInventory.Add(item.ItemID, item); m_taskInventory.Add(item.ItemID, item);
}
m_inventorySerial++; m_inventorySerial++;
} }
@ -201,11 +214,14 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
/// <param name="items"></param> /// <param name="items"></param>
public void AddInventoryItems(ICollection<TaskInventoryItem> items) public void AddInventoryItems(ICollection<TaskInventoryItem> items)
{
lock (m_taskInventory)
{ {
foreach (TaskInventoryItem item in items) foreach (TaskInventoryItem item in items)
{ {
m_taskInventory.Add(item.ItemID, item); m_taskInventory.Add(item.ItemID, item);
} }
}
m_inventorySerial++; m_inventorySerial++;
} }
@ -216,6 +232,8 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="itemID"></param> /// <param name="itemID"></param>
/// <returns>null if the item does not exist</returns> /// <returns>null if the item does not exist</returns>
public TaskInventoryItem GetInventoryItem(LLUUID itemID) public TaskInventoryItem GetInventoryItem(LLUUID itemID)
{
lock (m_taskInventory)
{ {
if (m_taskInventory.ContainsKey(itemID)) if (m_taskInventory.ContainsKey(itemID))
{ {
@ -228,6 +246,7 @@ namespace OpenSim.Region.Environment.Scenes
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
itemID, Name, UUID); itemID, Name, UUID);
} }
}
return null; return null;
} }
@ -239,6 +258,8 @@ namespace OpenSim.Region.Environment.Scenes
/// in this prim's inventory.</param> /// in this prim's inventory.</param>
/// <returns>false if the item did not exist, true if the update occurred succesfully</returns> /// <returns>false if the item did not exist, true if the update occurred succesfully</returns>
public bool UpdateInventoryItem(TaskInventoryItem item) public bool UpdateInventoryItem(TaskInventoryItem item)
{
lock (m_taskInventory)
{ {
if (m_taskInventory.ContainsKey(item.ItemID)) if (m_taskInventory.ContainsKey(item.ItemID))
{ {
@ -254,6 +275,7 @@ namespace OpenSim.Region.Environment.Scenes
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
item.ItemID, Name, UUID); item.ItemID, Name, UUID);
} }
}
return false; return false;
} }
@ -265,6 +287,8 @@ namespace OpenSim.Region.Environment.Scenes
/// <returns>Numeric asset type of the item removed. Returns -1 if the item did not exist /// <returns>Numeric asset type of the item removed. Returns -1 if the item did not exist
/// in this prim's inventory.</returns> /// in this prim's inventory.</returns>
public int RemoveInventoryItem(LLUUID itemID) public int RemoveInventoryItem(LLUUID itemID)
{
lock (m_taskInventory)
{ {
if (m_taskInventory.ContainsKey(itemID)) if (m_taskInventory.ContainsKey(itemID))
{ {
@ -281,6 +305,7 @@ namespace OpenSim.Region.Environment.Scenes
"Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
itemID, Name, UUID); itemID, Name, UUID);
} }
}
return -1; return -1;
} }
@ -309,6 +334,9 @@ namespace OpenSim.Region.Environment.Scenes
{ {
byte[] fileData = new byte[0]; byte[] fileData = new byte[0];
InventoryStringBuilder invString = new InventoryStringBuilder(m_folderID, UUID); InventoryStringBuilder invString = new InventoryStringBuilder(m_folderID, UUID);
lock (m_taskInventory)
{
foreach (TaskInventoryItem item in m_taskInventory.Values) foreach (TaskInventoryItem item in m_taskInventory.Values)
{ {
invString.AddItemStart(); invString.AddItemStart();
@ -336,6 +364,7 @@ namespace OpenSim.Region.Environment.Scenes
invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
invString.AddSectionEnd(); invString.AddSectionEnd();
} }
}
fileData = Helpers.StringToField(invString.BuildString); fileData = Helpers.StringToField(invString.BuildString);

View File

@ -952,10 +952,10 @@ namespace OpenSim.Region.Environment.Scenes
#region Copying #region Copying
/// <summary> /// <summary>
/// /// Duplicates this part.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID) public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum)
{ {
SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone();
dupe.m_shape = m_shape.Copy(); dupe.m_shape = m_shape.Copy();
@ -978,6 +978,10 @@ namespace OpenSim.Region.Environment.Scenes
dupe.SalePrice = SalePrice; dupe.SalePrice = SalePrice;
dupe.Category = Category; dupe.Category = Category;
dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone();
dupe.ResetIDs(linkNum);
// This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
dupe.LastOwnerID = ObjectOwner; dupe.LastOwnerID = ObjectOwner;