Tidying Inventory
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2024, Sjofn LLC.
|
||||
* Copyright (c) 2021-2025, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -68,7 +68,7 @@ namespace OpenMetaverse
|
||||
/// the data sent from the simulator</param>
|
||||
protected virtual void OnInventoryObjectUpdated(InventoryObjectUpdatedEventArgs e)
|
||||
{
|
||||
EventHandler<InventoryObjectUpdatedEventArgs> handler = m_InventoryObjectUpdated;
|
||||
var handler = m_InventoryObjectUpdated;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace OpenMetaverse
|
||||
/// the data sent from the simulator</param>
|
||||
protected virtual void OnInventoryObjectRemoved(InventoryObjectRemovedEventArgs e)
|
||||
{
|
||||
EventHandler<InventoryObjectRemovedEventArgs> handler = m_InventoryObjectRemoved;
|
||||
var handler = m_InventoryObjectRemoved;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace OpenMetaverse
|
||||
/// the data sent from the simulator</param>
|
||||
protected virtual void OnInventoryObjectAdded(InventoryObjectAddedEventArgs e)
|
||||
{
|
||||
EventHandler<InventoryObjectAddedEventArgs> handler = m_InventoryObjectAdded;
|
||||
var handler = m_InventoryObjectAdded;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
@@ -197,12 +197,11 @@ namespace OpenMetaverse
|
||||
/// <exception cref="InventoryException">When <code>folder</code> does not exist in the inventory</exception>
|
||||
public List<InventoryBase> GetContents(UUID folder)
|
||||
{
|
||||
InventoryNode folderNode;
|
||||
if (!Items.TryGetValue(folder, out folderNode))
|
||||
if (!Items.TryGetValue(folder, out var folderNode))
|
||||
throw new InventoryException("Unknown folder: " + folder);
|
||||
lock (folderNode.Nodes.SyncRoot)
|
||||
{
|
||||
List<InventoryBase> contents = new List<InventoryBase>(folderNode.Nodes.Count);
|
||||
var contents = new List<InventoryBase>(folderNode.Nodes.Count);
|
||||
contents.AddRange(folderNode.Nodes.Values.Select(node => node.Data));
|
||||
return contents;
|
||||
}
|
||||
@@ -226,7 +225,7 @@ namespace OpenMetaverse
|
||||
if (item.ParentUUID != UUID.Zero && !Items.TryGetValue(item.ParentUUID, out itemParent))
|
||||
{
|
||||
// OK, we have no data on the parent, let's create a fake one.
|
||||
InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID)
|
||||
var fakeParent = new InventoryFolder(item.ParentUUID)
|
||||
{
|
||||
DescendentCount = 1 // Dear god, please forgive me.
|
||||
};
|
||||
@@ -239,10 +238,9 @@ namespace OpenMetaverse
|
||||
// item.ParentUUID.ToString() + " when we have no local reference to that folder", Client);
|
||||
}
|
||||
|
||||
InventoryNode itemNode;
|
||||
if (Items.TryGetValue(item.UUID, out itemNode)) // We're updating.
|
||||
if (Items.TryGetValue(item.UUID, out var itemNode)) // We're updating.
|
||||
{
|
||||
InventoryNode oldParent = itemNode.Parent;
|
||||
var oldParent = itemNode.Parent;
|
||||
// Handle parent change
|
||||
if (oldParent == null || itemParent == null || itemParent.Data.UUID != oldParent.Data.UUID)
|
||||
{
|
||||
@@ -292,8 +290,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
lock (Items)
|
||||
{
|
||||
InventoryNode node;
|
||||
if (Items.TryGetValue(item.UUID, out node))
|
||||
if (Items.TryGetValue(item.UUID, out var node))
|
||||
{
|
||||
if (node.Parent != null)
|
||||
{
|
||||
@@ -309,8 +306,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
// In case there's a new parent:
|
||||
InventoryNode newParent;
|
||||
if (Items.TryGetValue(item.ParentUUID, out newParent))
|
||||
if (Items.TryGetValue(item.ParentUUID, out var newParent))
|
||||
{
|
||||
lock (newParent.Nodes.SyncRoot)
|
||||
newParent.Nodes.Remove(item.UUID);
|
||||
@@ -345,7 +341,7 @@ namespace OpenMetaverse
|
||||
using (Stream stream = File.Open(filename, FileMode.Create))
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
var bformatter = new BinaryFormatter();
|
||||
#endif
|
||||
lock (Items)
|
||||
{
|
||||
@@ -374,8 +370,8 @@ namespace OpenMetaverse
|
||||
/// <returns>The number of inventory items successfully reconstructed into the inventory node tree</returns>
|
||||
public int RestoreFromDisk(string filename)
|
||||
{
|
||||
List<InventoryNode> nodes = new List<InventoryNode>();
|
||||
int item_count = 0;
|
||||
var nodes = new List<InventoryNode>();
|
||||
var itemCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -385,7 +381,7 @@ namespace OpenMetaverse
|
||||
using (Stream stream = File.Open(filename, FileMode.Open))
|
||||
{
|
||||
#if !NET7_0_OR_GREATER
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
var bformatter = new BinaryFormatter();
|
||||
#endif
|
||||
while (stream.Position < stream.Length)
|
||||
{
|
||||
@@ -396,7 +392,7 @@ namespace OpenMetaverse
|
||||
var node = (InventoryNode)bformatter.Deserialize(stream);
|
||||
nodes.Add(node);
|
||||
#endif
|
||||
item_count++;
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,48 +402,47 @@ namespace OpenMetaverse
|
||||
return -1;
|
||||
}
|
||||
|
||||
Logger.Log($"Read {item_count} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
Logger.Log($"Read {itemCount} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
|
||||
item_count = 0;
|
||||
List<InventoryNode> del_nodes = new List<InventoryNode>(); //nodes that we have processed and will delete
|
||||
List<UUID> dirty_folders = new List<UUID>(); // Tainted folders that we will not restore items into
|
||||
itemCount = 0;
|
||||
var delNodes = new List<InventoryNode>(); //nodes that we have processed and will delete
|
||||
var dirtyFolders = new List<UUID>(); // Tainted folders that we will not restore items into
|
||||
|
||||
// Because we could get child nodes before parents we must iterate around and only add nodes who have
|
||||
// a parent already in the list because we must update both child and parent to link together
|
||||
// But sometimes we have seen orphin nodes due to bad/incomplete data when caching so we have an emergency abort route
|
||||
int stuck = 0;
|
||||
var stuck = 0;
|
||||
|
||||
while (nodes.Count != 0 && stuck<5)
|
||||
{
|
||||
foreach (InventoryNode node in nodes)
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
InventoryNode pnode;
|
||||
if (node.ParentID == UUID.Zero)
|
||||
{
|
||||
//We don't need the root nodes "My Inventory" etc as they will already exist for the correct
|
||||
// user of this cache.
|
||||
del_nodes.Add(node);
|
||||
item_count--;
|
||||
delNodes.Add(node);
|
||||
itemCount--;
|
||||
}
|
||||
else if(Items.TryGetValue(node.Data.UUID,out pnode))
|
||||
else if(Items.TryGetValue(node.Data.UUID,out var pnode))
|
||||
{
|
||||
//We already have this it must be a folder
|
||||
if (node.Data is InventoryFolder cacheFolder)
|
||||
{
|
||||
InventoryFolder server_folder = (InventoryFolder)pnode.Data;
|
||||
var serverFolder = (InventoryFolder)pnode.Data;
|
||||
|
||||
if (cacheFolder.Version != server_folder.Version)
|
||||
if (cacheFolder.Version != serverFolder.Version)
|
||||
{
|
||||
Logger.DebugLog("Inventory Cache/Server version mismatch on " + node.Data.Name + " " + cacheFolder.Version + " vs " + server_folder.Version);
|
||||
Logger.DebugLog("Inventory Cache/Server version mismatch on " + node.Data.Name + " " + cacheFolder.Version + " vs " + serverFolder.Version);
|
||||
pnode.NeedsUpdate = true;
|
||||
dirty_folders.Add(node.Data.UUID);
|
||||
dirtyFolders.Add(node.Data.UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
pnode.NeedsUpdate = false;
|
||||
}
|
||||
|
||||
del_nodes.Add(node);
|
||||
delNodes.Add(node);
|
||||
}
|
||||
}
|
||||
else if (Items.TryGetValue(node.ParentID, out pnode))
|
||||
@@ -458,38 +453,38 @@ namespace OpenMetaverse
|
||||
// dirty and don't process nodes that belong to it
|
||||
if (node.Data is InventoryFolder && !(Items.ContainsKey(node.Data.UUID)))
|
||||
{
|
||||
dirty_folders.Add(node.Data.UUID);
|
||||
dirtyFolders.Add(node.Data.UUID);
|
||||
}
|
||||
|
||||
//Only add new items, this is most likely to be run at login time before any inventory
|
||||
//nodes other than the root are populated. Don't add non existing folders.
|
||||
if (!Items.ContainsKey(node.Data.UUID) && !dirty_folders.Contains(pnode.Data.UUID) && !(node.Data is InventoryFolder))
|
||||
//nodes other than the root are populated. Don't add non-existing folders.
|
||||
if (!Items.ContainsKey(node.Data.UUID) && !dirtyFolders.Contains(pnode.Data.UUID) && !(node.Data is InventoryFolder))
|
||||
{
|
||||
Items.Add(node.Data.UUID, node);
|
||||
node.Parent = pnode; //Update this node with its parent
|
||||
pnode.Nodes.Add(node.Data.UUID, node); // Add to the parents child list
|
||||
item_count++;
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
|
||||
del_nodes.Add(node);
|
||||
delNodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (del_nodes.Count == 0)
|
||||
if (delNodes.Count == 0)
|
||||
++stuck;
|
||||
else
|
||||
stuck = 0;
|
||||
|
||||
//Clean up processed nodes this loop around.
|
||||
foreach (InventoryNode node in del_nodes)
|
||||
foreach (var node in delNodes)
|
||||
nodes.Remove(node);
|
||||
|
||||
del_nodes.Clear();
|
||||
delNodes.Clear();
|
||||
}
|
||||
|
||||
Logger.Log($"Reassembled {item_count} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
return item_count;
|
||||
Logger.Log($"Reassembled {itemCount} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
return itemCount;
|
||||
}
|
||||
|
||||
#region Operators
|
||||
@@ -497,8 +492,8 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// By using the bracket operator on this class, the program can get the
|
||||
/// InventoryObject designated by the specified uuid. If the value for the corresponding
|
||||
/// UUID is null, the call is equivelant to a call to <code>RemoveNodeFor(this[uuid])</code>.
|
||||
/// If the value is non-null, it is equivelant to a call to <code>UpdateNodeFor(value)</code>,
|
||||
/// UUID is null, the call is equivalent to a call to <code>RemoveNodeFor(this[uuid])</code>.
|
||||
/// If the value is non-null, it is equivalent to a call to <code>UpdateNodeFor(value)</code>,
|
||||
/// the uuid parameter is ignored.
|
||||
/// </summary>
|
||||
/// <param name="uuid">The UUID of the InventoryObject to get or set, ignored if set to non-null value.</param>
|
||||
@@ -507,7 +502,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
get
|
||||
{
|
||||
InventoryNode node = Items[uuid];
|
||||
var node = Items[uuid];
|
||||
return node.Data;
|
||||
}
|
||||
set
|
||||
@@ -524,8 +519,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
else
|
||||
{
|
||||
InventoryNode node;
|
||||
if (Items.TryGetValue(uuid, out node))
|
||||
if (Items.TryGetValue(uuid, out var node))
|
||||
{
|
||||
RemoveNodeFor(node.Data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user