* 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
{
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));
@ -86,19 +92,38 @@ namespace OpenSim.Framework
// see IXmlSerializable
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);
}
// 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>
/// Represents an item in a task inventory
/// </summary>
public class TaskInventoryItem
public class TaskInventoryItem : ICloneable
{
/// <summary>
/// XXX This should really be factored out into some constants class.
@ -143,16 +168,6 @@ namespace OpenSim.Framework
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 ParentID = LLUUID.Zero; //parent folder id
@ -175,5 +190,21 @@ namespace OpenSim.Framework
public uint CreationDate = 0;
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);
copy.AbsolutePosition = copy.AbsolutePosition + offset;
copy.ResetIDs();
lock (Entities)
{
Entities.Add(copy.UUID, copy);
}
m_numPrim++;
copy.StartScripts();
copy.ScheduleGroupForFullUpdate();
}
}
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>
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.LinkNum = m_parts.Count;
m_parts.Add(newPart.UUID, newPart);
SetPartAsRoot(newPart);
}
@ -602,9 +601,8 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="part"></param>
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.LinkNum = m_parts.Count;
m_parts.Add(newPart.UUID, newPart);
SetPartAsNonRoot(newPart);
}

View File

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

View File

@ -952,10 +952,10 @@ namespace OpenSim.Region.Environment.Scenes
#region Copying
/// <summary>
///
/// Duplicates this part.
/// </summary>
/// <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();
dupe.m_shape = m_shape.Copy();
@ -978,6 +978,10 @@ namespace OpenSim.Region.Environment.Scenes
dupe.SalePrice = SalePrice;
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.
dupe.LastOwnerID = ObjectOwner;