2007-07-13 14:49:36 +00:00
/ *
2008-07-21 21:12:59 +00:00
* Copyright ( c ) 2007 - 2008 , openmetaverse . org
2007-07-13 14:49:36 +00:00
* All rights reserved .
*
* - Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* - Redistributions of source code must retain the above copyright notice , this
* list of conditions and the following disclaimer .
2008-07-21 21:12:59 +00:00
* - Neither the name of the openmetaverse . org nor the names
2007-07-13 14:49:36 +00:00
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
2009-02-26 20:41:39 +00:00
using System.IO ;
using System.Runtime.Serialization.Formatters.Binary ;
using System.Runtime.Serialization ;
2008-08-14 04:09:27 +00:00
2008-07-21 21:12:59 +00:00
namespace OpenMetaverse
2007-07-13 14:49:36 +00:00
{
2007-09-10 10:20:30 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Exception class to identify inventory exceptions
2007-07-13 14:49:36 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public class InventoryException : Exception
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
public InventoryException ( string message )
: base ( message ) { }
}
2008-07-29 21:36:53 +00:00
2008-08-21 01:19:06 +00:00
/// <summary>
/// Responsible for maintaining inventory structure. Inventory constructs nodes
/// and manages node children as is necessary to maintain a coherant hirarchy.
/// Other classes should not manipulate or create InventoryNodes explicitly. When
/// A node's parent changes (when a folder is moved, for example) simply pass
/// Inventory the updated InventoryFolder and it will make the appropriate changes
/// to its internal representation.
/// </summary>
public class Inventory
{
2007-07-14 00:27:23 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Delegate to use for the OnInventoryObjectUpdated event.
2007-07-14 00:27:23 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="oldObject">The state of the InventoryObject before the update occured.</param>
/// <param name="newObject">The state of the InventoryObject after the update occured.</param>
public delegate void InventoryObjectUpdated ( InventoryBase oldObject , InventoryBase newObject ) ;
2008-08-14 04:09:27 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Delegate to use for the OnInventoryObjectRemoved event.
2008-08-14 04:09:27 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="obj">The InventoryObject that was removed.</param>
public delegate void InventoryObjectRemoved ( InventoryBase obj ) ;
2008-08-14 04:09:27 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Delegate to use for the OnInventoryObjectUpdated event.
2008-08-14 04:09:27 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="obj">The InventoryObject that has been stored.</param>
public delegate void InventoryObjectAdded ( InventoryBase obj ) ;
2008-08-14 04:09:27 +00:00
2008-03-31 21:31:02 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Called when an InventoryObject's state is changed.
2008-03-31 21:31:02 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public event InventoryObjectUpdated OnInventoryObjectUpdated ;
2007-09-10 10:20:30 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Called when an item or folder is removed from inventory.
2007-09-10 10:20:30 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public event InventoryObjectRemoved OnInventoryObjectRemoved ;
2008-08-12 05:55:42 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Called when an item is first added to the local inventory store.
/// This will occur most frequently when we're initially downloading
/// the inventory from the server.
///
/// This will also fire when another avatar or object offers us inventory
2008-08-12 05:55:42 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public event InventoryObjectAdded OnInventoryObjectAdded ;
2008-07-29 21:36:53 +00:00
2008-08-12 05:55:42 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// The root folder of this avatars inventory
2008-08-12 05:55:42 +00:00
/// </summary>
2008-07-29 21:36:53 +00:00
public InventoryFolder RootFolder
{
2008-08-21 01:19:06 +00:00
get { return RootNode . Data as InventoryFolder ; }
set
2008-08-05 05:07:53 +00:00
{
2008-08-21 01:19:06 +00:00
UpdateNodeFor ( value ) ;
_RootNode = Items [ value . UUID ] ;
2008-08-05 05:07:53 +00:00
}
}
2007-07-13 14:49:36 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// The default shared library folder
2007-07-13 14:49:36 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public InventoryFolder LibraryFolder
2008-07-29 23:38:07 +00:00
{
2008-08-21 01:19:06 +00:00
get { return LibraryRootNode . Data as InventoryFolder ; }
set
2008-05-05 10:32:47 +00:00
{
2008-08-21 01:19:06 +00:00
UpdateNodeFor ( value ) ;
_LibraryRootNode = Items [ value . UUID ] ;
2008-05-05 10:32:47 +00:00
}
}
2008-08-21 01:19:06 +00:00
private InventoryNode _LibraryRootNode ;
private InventoryNode _RootNode ;
2007-07-13 14:49:36 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// The root node of the avatars inventory
2007-07-13 14:49:36 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public InventoryNode RootNode
2007-11-06 09:26:10 +00:00
{
2008-08-21 01:19:06 +00:00
get
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
if ( _RootNode = = null )
throw new InventoryException ( "Root node unknown. Are you completely logged in?" ) ;
return _RootNode ;
2007-11-06 09:26:10 +00:00
}
}
2007-07-13 14:49:36 +00:00
2008-05-05 10:32:47 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// The root node of the default shared library
2008-05-05 10:32:47 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
public InventoryNode LibraryRootNode
2008-05-05 10:32:47 +00:00
{
2008-08-21 01:19:06 +00:00
get
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
if ( _LibraryRootNode = = null )
throw new InventoryException ( "Library Root node unknown. Are you completely logged in?" ) ;
return _LibraryRootNode ;
2008-05-05 10:32:47 +00:00
}
}
2008-08-21 01:19:06 +00:00
public UUID Owner {
get { return _Owner ; }
2007-07-13 14:49:36 +00:00
}
2008-08-21 01:19:06 +00:00
private UUID _Owner ;
2007-07-13 14:49:36 +00:00
2008-08-21 01:19:06 +00:00
private GridClient Client ;
2008-10-09 16:48:44 +00:00
//private InventoryManager Manager;
2009-06-27 20:51:14 +00:00
public Dictionary < UUID , InventoryNode > Items = new Dictionary < UUID , InventoryNode > ( ) ;
2008-08-14 04:09:27 +00:00
2008-08-21 01:19:06 +00:00
public Inventory ( GridClient client , InventoryManager manager )
: this ( client , manager , client . Self . AgentID ) { }
2008-08-14 04:09:27 +00:00
2008-08-21 01:19:06 +00:00
public Inventory ( GridClient client , InventoryManager manager , UUID owner )
{
Client = client ;
2008-10-09 16:48:44 +00:00
//Manager = manager;
2008-08-21 01:19:06 +00:00
_Owner = owner ;
if ( owner = = UUID . Zero )
Logger . Log ( "Inventory owned by nobody!" , Helpers . LogLevel . Warning , Client ) ;
Items = new Dictionary < UUID , InventoryNode > ( ) ;
2007-07-13 14:49:36 +00:00
}
2008-08-21 01:19:06 +00:00
public List < InventoryBase > GetContents ( InventoryFolder folder )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
return GetContents ( folder . UUID ) ;
2008-07-29 21:36:53 +00:00
}
/// <summary>
2008-08-21 01:19:06 +00:00
/// Returns the contents of the specified folder
2008-07-29 21:36:53 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="folder">A folder's UUID</param>
/// <returns>The contents of the folder corresponding to <code>folder</code></returns>
/// <exception cref="InventoryException">When <code>folder</code> does not exist in the inventory</exception>
public List < InventoryBase > GetContents ( UUID folder )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
InventoryNode folderNode ;
if ( ! Items . TryGetValue ( folder , out folderNode ) )
throw new InventoryException ( "Unknown folder: " + folder ) ;
lock ( folderNode . Nodes . SyncRoot )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
List < InventoryBase > contents = new List < InventoryBase > ( folderNode . Nodes . Count ) ;
foreach ( InventoryNode node in folderNode . Nodes . Values )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
contents . Add ( node . Data ) ;
2007-07-13 14:49:36 +00:00
}
2008-08-21 01:19:06 +00:00
return contents ;
2008-08-12 05:55:42 +00:00
}
}
/// <summary>
2008-08-21 01:19:06 +00:00
/// Updates the state of the InventoryNode and inventory data structure that
/// is responsible for the InventoryObject. If the item was previously not added to inventory,
/// it adds the item, and updates structure accordingly. If it was, it updates the
/// InventoryNode, changing the parent node if <code>item.parentUUID</code> does
/// not match <code>node.Parent.Data.UUID</code>.
///
/// You can not set the inventory root folder using this method
2008-08-12 05:55:42 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="item">The InventoryObject to store</param>
public void UpdateNodeFor ( InventoryBase item )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
lock ( Items )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
InventoryNode itemParent = null ;
if ( item . ParentUUID ! = UUID . Zero & & ! Items . TryGetValue ( item . ParentUUID , out itemParent ) )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
// OK, we have no data on the parent, let's create a fake one.
InventoryFolder fakeParent = new InventoryFolder ( item . ParentUUID ) ;
fakeParent . DescendentCount = 1 ; // Dear god, please forgive me.
itemParent = new InventoryNode ( fakeParent ) ;
Items [ item . ParentUUID ] = itemParent ;
// Unfortunately, this breaks the nice unified tree
// while we're waiting for the parent's data to come in.
// As soon as we get the parent, the tree repairs itself.
Logger . DebugLog ( "Attempting to update inventory child of " +
item . ParentUUID . ToString ( ) + " when we have no local reference to that folder" , Client ) ;
if ( Client . Settings . FETCH_MISSING_INVENTORY )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
// Fetch the parent
List < UUID > fetchreq = new List < UUID > ( 1 ) ;
fetchreq . Add ( item . ParentUUID ) ;
//Manager.FetchInventory(fetchreq); // we cant fetch folder data! :-O
2008-08-12 05:55:42 +00:00
}
}
2008-08-21 01:19:06 +00:00
InventoryNode itemNode ;
if ( Items . TryGetValue ( item . UUID , out itemNode ) ) // We're updating.
{
InventoryNode oldParent = itemNode . Parent ;
// Handle parent change
if ( oldParent = = null | | itemParent = = null | | itemParent . Data . UUID ! = oldParent . Data . UUID )
2008-08-12 05:55:42 +00:00
{
2008-08-21 01:19:06 +00:00
if ( oldParent ! = null )
2007-11-06 09:26:10 +00:00
{
2008-08-21 01:19:06 +00:00
lock ( oldParent . Nodes . SyncRoot )
oldParent . Nodes . Remove ( item . UUID ) ;
}
if ( itemParent ! = null )
{
lock ( itemParent . Nodes . SyncRoot )
itemParent . Nodes [ item . UUID ] = itemNode ;
2007-11-06 09:26:10 +00:00
}
2007-07-13 14:49:36 +00:00
}
2008-08-21 01:19:06 +00:00
itemNode . Parent = itemParent ;
2008-07-29 21:36:53 +00:00
2009-06-15 17:45:34 +00:00
FireOnInventoryObjectUpdated ( itemNode . Data , item ) ;
2008-07-29 21:36:53 +00:00
2008-08-21 01:19:06 +00:00
itemNode . Data = item ;
2008-08-14 04:09:27 +00:00
}
2008-08-21 01:19:06 +00:00
else // We're adding.
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
itemNode = new InventoryNode ( item , itemParent ) ;
Items . Add ( item . UUID , itemNode ) ;
FireOnInventoryObjectAdded ( item ) ;
2007-07-13 14:49:36 +00:00
}
}
}
2008-08-21 01:19:06 +00:00
public InventoryNode GetNodeFor ( UUID uuid )
2008-03-31 21:31:02 +00:00
{
2008-08-21 01:19:06 +00:00
return Items [ uuid ] ;
2008-03-31 21:31:02 +00:00
}
2007-07-13 14:49:36 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// Removes the InventoryObject and all related node data from Inventory.
2007-07-13 14:49:36 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="item">The InventoryObject to remove.</param>
public void RemoveNodeFor ( InventoryBase item )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
lock ( Items )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
InventoryNode node ;
if ( Items . TryGetValue ( item . UUID , out node ) )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
if ( node . Parent ! = null )
lock ( node . Parent . Nodes . SyncRoot )
node . Parent . Nodes . Remove ( item . UUID ) ;
Items . Remove ( item . UUID ) ;
FireOnInventoryObjectRemoved ( item ) ;
2007-07-13 14:49:36 +00:00
}
2008-08-21 01:19:06 +00:00
// In case there's a new parent:
InventoryNode newParent ;
if ( Items . TryGetValue ( item . ParentUUID , out newParent ) )
2007-07-13 14:49:36 +00:00
{
2008-08-21 01:19:06 +00:00
lock ( newParent . Nodes . SyncRoot )
newParent . Nodes . Remove ( item . UUID ) ;
2007-07-13 14:49:36 +00:00
}
}
}
/// <summary>
2008-08-21 01:19:06 +00:00
/// Used to find out if Inventory contains the InventoryObject
/// specified by <code>uuid</code>.
2008-07-29 21:36:53 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="uuid">The UUID to check.</param>
/// <returns>true if inventory contains uuid, false otherwise</returns>
public bool Contains ( UUID uuid )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
return Items . ContainsKey ( uuid ) ;
2008-07-29 21:36:53 +00:00
}
2008-08-21 01:19:06 +00:00
public bool Contains ( InventoryBase obj )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
return Contains ( obj . UUID ) ;
2008-07-29 21:36:53 +00:00
}
2009-02-26 20:41:39 +00:00
/// <summary>
2009-06-27 20:51:14 +00:00
/// Saves the current inventory structure to a cache file
2009-02-26 20:41:39 +00:00
/// </summary>
/// <param name="filename">Name of the cache file to save to</param>
2009-06-27 20:51:14 +00:00
public void SaveToDisk ( string filename )
2009-06-28 16:13:58 +00:00
{
try
2009-06-27 20:51:14 +00:00
{
Stream stream = File . Open ( filename , FileMode . Create ) ;
BinaryFormatter bformatter = new BinaryFormatter ( ) ;
lock ( Items )
{
Logger . Log ( "Caching " + Items . Count . ToString ( ) + " inventory items to " + filename , Helpers . LogLevel . Info ) ;
foreach ( KeyValuePair < UUID , InventoryNode > kvp in Items )
{
bformatter . Serialize ( stream , kvp . Value ) ;
}
}
2009-06-28 16:13:58 +00:00
stream . Close ( ) ;
}
catch ( Exception e )
{
Logger . Log ( "Error saving inventory cache to disk :" + e . Message , Helpers . LogLevel . Error ) ;
2009-02-26 20:41:39 +00:00
}
}
/// <summary>
/// Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful.
/// </summary>
2009-06-28 16:13:58 +00:00
/// <param name="filename">Name of the cache file to load</param>
2009-06-27 20:51:14 +00:00
/// <returns>The number of inventory items sucessfully reconstructed into the inventory node tree</returns>
public int RestoreFromDisk ( string filename )
2009-02-26 20:41:39 +00:00
{
List < InventoryNode > nodes = new List < InventoryNode > ( ) ;
int item_count = 0 ;
try
{
if ( ! File . Exists ( filename ) )
2009-06-27 20:51:14 +00:00
return - 1 ;
2009-02-26 20:41:39 +00:00
Stream stream = File . Open ( filename , FileMode . Open ) ;
BinaryFormatter bformatter = new BinaryFormatter ( ) ;
2009-06-27 20:51:14 +00:00
2009-02-26 20:41:39 +00:00
while ( stream . Position < stream . Length )
{
OpenMetaverse . InventoryNode node = ( InventoryNode ) bformatter . Deserialize ( stream ) ;
nodes . Add ( node ) ;
item_count + + ;
}
stream . Close ( ) ;
}
catch ( Exception e )
{
Logger . Log ( "Error accessing inventory cache file :" + e . Message , Helpers . LogLevel . Error ) ;
2009-06-27 20:51:14 +00:00
return - 1 ;
2009-02-26 20:41:39 +00:00
}
Logger . Log ( "Read " + item_count . ToString ( ) + " items from inventory cache file" , Helpers . LogLevel . Info ) ;
item_count = 0 ;
2009-06-27 20:51:14 +00:00
List < InventoryNode > del_nodes = new List < InventoryNode > ( ) ; //nodes that we have processed and will delete
2009-02-26 20:41:39 +00:00
2009-06-27 20:51:14 +00:00
// Because we could get child nodes before parents we must itterate around and only add nodes who have
2009-02-26 20:41:39 +00:00
// a parent already in the list because we must update both child and parent to link together
2009-06-28 16:13:58 +00:00
// But sometimes we have seen orphin nodes due to bad/incomplete data when caching so we have an emergency abort route
2009-06-27 20:51:14 +00:00
int stuck = 0 ;
while ( nodes . Count ! = 0 & & stuck < 5 )
2009-02-26 20:41:39 +00:00
{
foreach ( InventoryNode 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 ) ;
2009-06-27 20:51:14 +00:00
item_count - - ;
}
else if ( Items . TryGetValue ( node . Data . UUID , out pnode ) )
{
//We already have this it must be a folder
if ( node . Data is InventoryFolder )
{
InventoryFolder cache_folder = ( InventoryFolder ) node . Data ;
InventoryFolder server_folder = ( InventoryFolder ) pnode . Data ;
if ( cache_folder . Version ! = server_folder . Version )
{
Logger . DebugLog ( "Inventory Cache/Server version mismatch on " + node . Data . Name + " " + cache_folder . Version . ToString ( ) + " vs " + server_folder . Version . ToString ( ) ) ;
2009-06-28 16:13:58 +00:00
pnode . NeedsUpdate = true ;
2009-06-27 20:51:14 +00:00
}
del_nodes . Add ( node ) ;
}
2009-02-26 20:41:39 +00:00
}
else if ( Items . TryGetValue ( node . ParentID , out pnode ) )
{
if ( node . Data ! = null )
{
//Only add new items, this is most likely to be run at login time before any inventory
//nodes other than the root are populated.
if ( ! Items . ContainsKey ( node . Data . UUID ) )
{
2009-06-28 16:13:58 +00:00
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 + + ;
2009-02-26 20:41:39 +00:00
}
}
del_nodes . Add ( node ) ;
}
}
2009-06-27 20:51:14 +00:00
if ( del_nodes . Count = = 0 )
stuck + + ;
else
stuck = 0 ;
2009-02-26 20:41:39 +00:00
//Clean up processed nodes this loop around.
foreach ( InventoryNode node in del_nodes )
nodes . Remove ( node ) ;
del_nodes . Clear ( ) ;
}
Logger . Log ( "Reassembled " + item_count . ToString ( ) + " items from inventory cache file" , Helpers . LogLevel . Info ) ;
2009-06-27 20:51:14 +00:00
return item_count ;
2009-02-26 20:41:39 +00:00
}
2008-08-21 01:19:06 +00:00
#region Operators
2007-09-10 10:20:30 +00:00
/// <summary>
2008-08-21 01:19:06 +00:00
/// 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>,
/// the uuid parameter is ignored.
2007-09-10 10:20:30 +00:00
/// </summary>
2008-08-21 01:19:06 +00:00
/// <param name="uuid">The UUID of the InventoryObject to get or set, ignored if set to non-null value.</param>
/// <returns>The InventoryObject corresponding to <code>uuid</code>.</returns>
public InventoryBase this [ UUID uuid ]
2007-09-10 10:20:30 +00:00
{
get
{
2008-08-21 01:19:06 +00:00
InventoryNode node = Items [ uuid ] ;
return node . Data ;
2008-07-29 21:36:53 +00:00
}
2008-08-21 01:19:06 +00:00
set
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
if ( value ! = null )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
// Log a warning if there is a UUID mismatch, this will cause problems
if ( value . UUID ! = uuid )
Logger . Log ( "Inventory[uuid]: uuid " + uuid . ToString ( ) + " is not equal to value.UUID " +
value . UUID . ToString ( ) , Helpers . LogLevel . Warning , Client ) ;
2008-07-29 21:36:53 +00:00
2008-08-21 01:19:06 +00:00
UpdateNodeFor ( value ) ;
}
else
2007-09-10 10:20:30 +00:00
{
2008-08-21 01:19:06 +00:00
InventoryNode node ;
if ( Items . TryGetValue ( uuid , out node ) )
2007-09-10 10:20:30 +00:00
{
2008-08-21 01:19:06 +00:00
RemoveNodeFor ( node . Data ) ;
2007-09-10 10:20:30 +00:00
}
}
}
}
2008-08-21 01:19:06 +00:00
#endregion Operators
2008-07-29 21:36:53 +00:00
2008-08-21 01:19:06 +00:00
#region Event Firing
2008-07-29 21:36:53 +00:00
2008-08-21 01:19:06 +00:00
protected void FireOnInventoryObjectUpdated ( InventoryBase oldObject , InventoryBase newObject )
{
if ( OnInventoryObjectUpdated ! = null )
2007-09-10 10:20:30 +00:00
{
2008-08-21 01:19:06 +00:00
try { OnInventoryObjectUpdated ( oldObject , newObject ) ; }
catch ( Exception e ) { Logger . Log ( e . Message , Helpers . LogLevel . Error , Client , e ) ; }
2007-09-10 10:20:30 +00:00
}
2007-07-13 14:49:36 +00:00
}
2007-09-10 10:20:30 +00:00
2008-08-21 01:19:06 +00:00
protected void FireOnInventoryObjectRemoved ( InventoryBase obj )
2008-07-29 21:36:53 +00:00
{
2008-08-21 01:19:06 +00:00
if ( OnInventoryObjectRemoved ! = null )
2008-08-14 04:09:27 +00:00
{
2008-08-21 01:19:06 +00:00
try { OnInventoryObjectRemoved ( obj ) ; }
catch ( Exception e ) { Logger . Log ( e . Message , Helpers . LogLevel . Error , Client , e ) ; }
2008-07-29 21:36:53 +00:00
}
}
2008-08-21 01:19:06 +00:00
protected void FireOnInventoryObjectAdded ( InventoryBase obj )
2008-08-05 05:07:53 +00:00
{
2008-08-21 01:19:06 +00:00
if ( OnInventoryObjectAdded ! = null )
2008-03-31 21:31:02 +00:00
{
2008-08-21 01:19:06 +00:00
try { OnInventoryObjectAdded ( obj ) ; }
catch ( Exception e ) { Logger . Log ( e . Message , Helpers . LogLevel . Error , Client , e ) ; }
2008-03-31 21:31:02 +00:00
}
}
2007-09-10 10:20:30 +00:00
#endregion
2007-07-13 14:49:36 +00:00
}
}