* 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));
@ -86,19 +92,38 @@ namespace OpenSim.Framework
// see IXmlSerializable // see IXmlSerializable
public void WriteXml(XmlWriter writer) public void WriteXml(XmlWriter writer)
{ {
foreach (TaskInventoryItem item in Values) lock (this)
{ {
tiiSerializer.Serialize(writer, item); foreach (TaskInventoryItem item in Values)
{
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.
@ -141,17 +166,7 @@ namespace OpenSim.Framework
String.Empty, String.Empty,
"lsltext", "lsltext",
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

@ -88,13 +88,16 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="linkNum'>Link number for the part</param> /// <param name="linkNum'>Link number for the part</param>
public void ResetInventoryIDs() public void ResetInventoryIDs()
{ {
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values); lock (TaskInventory)
TaskInventory.Clear(); {
IList<TaskInventoryItem> items = new List<TaskInventoryItem>(TaskInventory.Values);
foreach (TaskInventoryItem item in items) TaskInventory.Clear();
{
item.ResetIDs(UUID); foreach (TaskInventoryItem item in items)
TaskInventory.Add(item.ItemID, item); {
item.ResetIDs(UUID);
TaskInventory.Add(item.ItemID, item);
}
} }
} }
@ -103,12 +106,15 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
public void StartScripts() public void StartScripts()
{ {
foreach (TaskInventoryItem item in m_taskInventory.Values) lock (m_taskInventory)
{ {
// XXX more hardcoding badness. Should be an enum in TaskInventoryItem foreach (TaskInventoryItem item in m_taskInventory.Values)
if (10 == item.Type)
{ {
StartScript(item); // XXX more hardcoding badness. Should be an enum in TaskInventoryItem
if (10 == item.Type)
{
StartScript(item);
}
} }
} }
} }
@ -149,18 +155,20 @@ namespace OpenSim.Region.Environment.Scenes
/// </param> /// </param>
public void StartScript(LLUUID itemId) public void StartScript(LLUUID itemId)
{ {
if (m_taskInventory.ContainsKey(itemId)) lock (m_taskInventory)
{ {
StartScript(m_taskInventory[itemId]); if (m_taskInventory.ContainsKey(itemId))
} {
else StartScript(m_taskInventory[itemId]);
{ }
MainLog.Instance.Error( else
"PRIMINVENTORY", {
"Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", MainLog.Instance.Error(
itemId, Name, UUID); "PRIMINVENTORY",
} "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
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;
m_taskInventory.Add(item.ItemID, item);
lock (m_taskInventory)
{
m_taskInventory.Add(item.ItemID, item);
}
m_inventorySerial++; m_inventorySerial++;
} }
@ -202,9 +215,12 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="items"></param> /// <param name="items"></param>
public void AddInventoryItems(ICollection<TaskInventoryItem> items) public void AddInventoryItems(ICollection<TaskInventoryItem> items)
{ {
foreach (TaskInventoryItem item in items) lock (m_taskInventory)
{ {
m_taskInventory.Add(item.ItemID, item); foreach (TaskInventoryItem item in items)
{
m_taskInventory.Add(item.ItemID, item);
}
} }
m_inventorySerial++; m_inventorySerial++;
@ -217,16 +233,19 @@ namespace OpenSim.Region.Environment.Scenes
/// <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)
{ {
if (m_taskInventory.ContainsKey(itemID)) lock (m_taskInventory)
{ {
return m_taskInventory[itemID]; if (m_taskInventory.ContainsKey(itemID))
} {
else return m_taskInventory[itemID];
{ }
MainLog.Instance.Error( else
"PRIMINVENTORY", {
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", MainLog.Instance.Error(
itemID, Name, UUID); "PRIMINVENTORY",
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
itemID, Name, UUID);
}
} }
return null; return null;
@ -240,20 +259,23 @@ namespace OpenSim.Region.Environment.Scenes
/// <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)
{ {
if (m_taskInventory.ContainsKey(item.ItemID)) lock (m_taskInventory)
{ {
m_taskInventory[item.ItemID] = item; if (m_taskInventory.ContainsKey(item.ItemID))
m_inventorySerial++; {
m_taskInventory[item.ItemID] = item;
return true; m_inventorySerial++;
return true;
}
else
{
MainLog.Instance.Error(
"PRIMINVENTORY",
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
item.ItemID, Name, UUID);
}
} }
else
{
MainLog.Instance.Error(
"PRIMINVENTORY",
"Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
item.ItemID, Name, UUID);
}
return false; return false;
} }
@ -266,21 +288,24 @@ namespace OpenSim.Region.Environment.Scenes
/// in this prim's inventory.</returns> /// in this prim's inventory.</returns>
public int RemoveInventoryItem(LLUUID itemID) public int RemoveInventoryItem(LLUUID itemID)
{ {
if (m_taskInventory.ContainsKey(itemID)) lock (m_taskInventory)
{ {
int type = m_taskInventory[itemID].InvType; if (m_taskInventory.ContainsKey(itemID))
m_taskInventory.Remove(itemID); {
m_inventorySerial++; int type = m_taskInventory[itemID].InvType;
m_taskInventory.Remove(itemID);
return type; m_inventorySerial++;
return type;
}
else
{
MainLog.Instance.Error(
"PRIMINVENTORY",
"Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
itemID, Name, UUID);
}
} }
else
{
MainLog.Instance.Error(
"PRIMINVENTORY",
"Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
itemID, Name, UUID);
}
return -1; return -1;
} }
@ -309,32 +334,36 @@ 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);
foreach (TaskInventoryItem item in m_taskInventory.Values)
{ lock (m_taskInventory)
invString.AddItemStart(); {
invString.AddNameValueLine("item_id", item.ItemID.ToString()); foreach (TaskInventoryItem item in m_taskInventory.Values)
invString.AddNameValueLine("parent_id", item.ParentID.ToString()); {
invString.AddItemStart();
invString.AddPermissionsStart(); invString.AddNameValueLine("item_id", item.ItemID.ToString());
invString.AddNameValueLine("base_mask", "0x7FFFFFFF"); invString.AddNameValueLine("parent_id", item.ParentID.ToString());
invString.AddNameValueLine("owner_mask", "0x7FFFFFFF");
invString.AddNameValueLine("group_mask", "0x7FFFFFFF"); invString.AddPermissionsStart();
invString.AddNameValueLine("everyone_mask", "0x7FFFFFFF"); invString.AddNameValueLine("base_mask", "0x7FFFFFFF");
invString.AddNameValueLine("next_owner_mask", "0x7FFFFFFF"); invString.AddNameValueLine("owner_mask", "0x7FFFFFFF");
invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); invString.AddNameValueLine("group_mask", "0x7FFFFFFF");
invString.AddNameValueLine("owner_id", item.OwnerID.ToString()); invString.AddNameValueLine("everyone_mask", "0x7FFFFFFF");
invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); invString.AddNameValueLine("next_owner_mask", "0x7FFFFFFF");
invString.AddNameValueLine("group_id", item.GroupID.ToString()); invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
invString.AddSectionEnd(); invString.AddNameValueLine("owner_id", item.OwnerID.ToString());
invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
invString.AddNameValueLine("asset_id", item.AssetID.ToString()); invString.AddNameValueLine("group_id", item.GroupID.ToString());
invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); invString.AddSectionEnd();
invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
invString.AddNameValueLine("flags", "0x00"); invString.AddNameValueLine("asset_id", item.AssetID.ToString());
invString.AddNameValueLine("name", item.Name + "|"); invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
invString.AddNameValueLine("desc", item.Description + "|"); invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); invString.AddNameValueLine("flags", "0x00");
invString.AddSectionEnd(); invString.AddNameValueLine("name", item.Name + "|");
invString.AddNameValueLine("desc", item.Description + "|");
invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
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();
@ -977,6 +977,10 @@ namespace OpenSim.Region.Environment.Scenes
dupe.ObjectSaleType = ObjectSaleType; dupe.ObjectSaleType = ObjectSaleType;
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;